2014-01-11 57 views
0

假設我有一個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 

不應該的日期在這種情況下進行排序?

+2

因爲'where [Name] like'A%''返回以'A'開頭的行,並且您希望resultset被'Date'排序,所以需要進行排序。它不需要爲'WHERE [Name] ='whatever'ORDER BY [Date] asc'進行排序。 – a1ex07

回答

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.通常不是手動強制索引的最佳做法 - 讓優化器選擇。

相關問題