我有一个SQL语句,我试图优化以删除排序运算符
SELECT *,ROW_NUMBER() OVER (
PARTITION BY RuleInstanceId
ORDER BY [Timestamp] DESC
) AS rn
FROM RuleInstanceHistoricalMembership
我读过的所有内容(例如Optimizing SQL queries by removing Sort operator in Execution plan)都表明这是要添加的正确索引,但它似乎根本没有效果。
CREATE NONCLUSTERED INDEX IX_MyIndex ON dbo.[RuleInstanceHistoricalMembership](RuleInstanceId, [Timestamp] DESC)
我必须遗漏一些东西,因为我已阅读大量文章,似乎都认为跨越两个专栏的索引应解决此问题
答案 0 :(得分:9)
从技术上讲,您添加的索引可以避免排序。
但是,您创建的索引是非覆盖的,因此SQL Server还需要执行6000万次密钥查找回基表。
简单地扫描聚集索引并在运行中对其进行排序的成本比该选项便宜得多。
为了让索引自动使用,你需要。
SELECT
列表中删除列,以便索引覆盖它。INCLUDE
- d列添加到索引。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
顺序。