技術上已添加做索引可以讓你避免排序。
但是,您創建的索引不覆蓋,因此SQL Server將需要執行6千萬個密鑰查找返回基表。
簡單地掃描聚集索引並在運行中對其進行排序的成本比該選項便宜得多。
爲了讓索引自動使用,你需要兩者之一。
- 刪除查詢
SELECT
列中的列,以便索引覆蓋它。
- 將
INCLUDE
-d列添加到索引。
BTW:對於6000萬行的表,你可能會發現,即使你試圖對非覆蓋索引生效的問題與索引提示你還沒有得到避免的預期效果一種排序。
CREATE TABLE RuleInstanceHistoricalMembership
(
ID INT PRIMARY KEY,
Col2 INT,
Col3 INT,
RuleInstanceId INT,
[Timestamp] INT
)
CREATE NONCLUSTERED INDEX IX_MyIndex
ON dbo.[RuleInstanceHistoricalMembership](RuleInstanceId, [Timestamp] DESC)
/*Fake small table*/
UPDATE STATISTICS RuleInstanceHistoricalMembership
WITH ROWCOUNT = 600,
PAGECOUNT = 10
SELECT *,
ROW_NUMBER() OVER (PARTITION BY RuleInstanceId
ORDER BY [Timestamp] DESC) AS rn
FROM RuleInstanceHistoricalMembership WITH (INDEX = IX_MyIndex)
給人的計劃
由於沒有排序,但構成該行和頁數
/*Fake large table*/
UPDATE STATISTICS RuleInstanceHistoricalMembership
WITH ROWCOUNT = 60000000,
PAGECOUNT = 10000000
,然後再試一次,你會得到
現在它有兩種!
NCI上的掃描是RuleInstanceId, Timestamp DESC
順序,但隨後SQL Server將其重新排列爲每Optimizing I/O Performance by Sorting的聚簇索引鍵順序(Id ASC
)。
此步驟旨在嘗試將6000萬隨機查詢的預期大規模成本降低到聚集索引。然後它被分類回原來的RuleInstanceId, Timestamp DESC
命令,該索引交付它。
當你改變'select *'爲'select RuleInstanceID,Timestamp' – iruvar
@ 1_CR,使它消失,我需要索引跨越所有選定的列也? –
對於select *,它基本上是優化器在非聚簇索引的每一行的聚簇索引查找和全表掃描之間的選擇 - 在選擇後者時可能是合理的。您可以通過「包含」列將所有其他列作爲「有效載荷」添加到非聚集索引中,以避免訪問聚集索引,但不知道更多關於數據量的信息等,很難知道這是否是明智的選擇 – iruvar