假设我有一张包含ID,名称和日期的表格。
我有一个非聚集索引,如
CREATE NONCLUSTERED INDEX IX_Test_NameDate ON [dbo].[Test] (Name, Date)
当我运行查询时,
select
[Name], [Date]
from
[dbo].[Test] WITH (INDEX(IX_Test_NameDate))
where
[Name] like 'A%'
order by
[Date] asc
我参与了SQL Server的执行计划,
Select <-- Sort <-- Index Seek (NonClustered)
为什么排序?日期是否已在非聚集索引中排序?什么是更好的非聚集索引看起来不需要排序(只有索引搜索)。
(不能使用聚簇索引,因为此示例是具有多行/索引的更大示例的精简版本。)
例如,我得到了一个类似于
的表的执行计划(带排序)ID Name Date
1 A 2014-01-01
2 A 2014-02-01
3 A 2014-03-01
4 A 2014-04-01
5 B 2014-01-01
6 B 2014-02-01
7 B 2014-03-01
8 B 2014-04-01
9 B 2014-05-01
10 B 2014-06-01
在这种情况下,日期不应该排序吗?
答案 0 :(得分:2)
不,Date
列不是“已经在非聚集索引中排序”,至少不是本身。它在 Name
之后排序。
考虑以下简单的表格数据:
Name Date
----- --------
Allen 1/1/2014
Barb 1/1/2013
Charlie 1/1/2015
Darlene 1/1/2012
Ernie 1/1/2016
Faith 1/1/2011
按Name
排序后,Date
列可能会出现故障。保证日期仅适用于具有相同Name
的行。
你的目标是彼此交叉的目的。您需要多个名称 - 因此数据最好按名称排序,以便可以进行搜索,但是您希望按日期排序。您如何建议存储上面的六行表,以便按日期对每个可能的名称范围进行排序?
如果有关于名称范围的某种规律性或模式(例如,您始终仅按首字母拉取名称),则可能存在解决方法。
ALTER TABLE dbo.Test ADD NamePrefix AS (Left(Name, 1)) PERSISTED;
CREATE NONCLUSTERED INDEX IX_Test_NamePrefix_Date ON dbo.Test (NamePrefix, Date);
现在这个查询理论上不需要执行排序:
SELECT Name, Date
FROM dbo.Test
WHERE NamePrefix = 'A'
ORDER BY Date;
请注意,添加像这样的持久计算列有一些可能的问题:增加数据大小,这种设计在几乎所有情况下几乎肯定都是错误的,计算列的扩散会非常糟糕,等等。
P.S。通常不是手动强制索引的最佳做法 - 让优化程序选择。