分区+;的正确SQL索引;取消排序的命令
我有一个SQL语句,我正试图优化它以删除排序运算符分区+;的正确SQL索引;取消排序的命令,sql,sql-server,performance,Sql,Sql Server,Performance,我有一个SQL语句,我正试图优化它以删除排序运算符 SELECT *,ROW_NUMBER() OVER ( PARTITION BY RuleInstanceId ORDER BY [Timestamp] DESC ) AS rn FROM RuleInstanceHistoricalMembership 我读到的所有内容都表明这是添加的正确索引,但它似乎没有任何效果 CREATE NONCLUSTERED INDEX IX_MyIndex ON db
SELECT *,ROW_NUMBER() OVER (
PARTITION BY RuleInstanceId
ORDER BY [Timestamp] DESC
) AS rn
FROM RuleInstanceHistoricalMembership
我读到的所有内容都表明这是添加的正确索引,但它似乎没有任何效果
CREATE NONCLUSTERED INDEX IX_MyIndex ON dbo.[RuleInstanceHistoricalMembership](RuleInstanceId, [Timestamp] DESC)
我一定是漏掉了什么,因为我读过大量的文章,这些文章似乎都建议跨两列的索引应该可以解决这个问题从技术上讲,您添加的索引确实允许您避免排序 但是,您创建的索引是非覆盖的,因此SQL Server还需要执行6000万个键查找,以返回基表 简单地扫描聚集索引并对其进行动态排序的成本要比该选项低得多 为了得到自动使用的索引,您需要执行以下操作之一
- 从查询
列表中删除列,以便索引覆盖它SELECT
- 在索引中添加
包含
-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根据将其重新排序为聚集索引键顺序(Id ASC
)
这一步是尝试减少对聚集索引进行6000万次随机查找的预期巨大成本。然后将其重新排序为原始的
RuleInstanceId,Timestamp DESC
顺序,索引将其交付。将select*
更改为select RuleInstanceId,Timestamp
@1\u CR时会发生什么,使其消失,我是否也需要索引来跨越所有选定的列?使用select*
,优化器基本上可以选择对非聚集索引的每一行进行聚集索引搜索和对整个表进行扫描—选择后者可能是合理的。您可以通过“include”列将所有其他列作为“payload”添加到非聚集索引中,以避免访问聚集索引,但在不了解更多数据量等信息的情况下,很难知道这是否明智choice@1_CR这是一个表,我希望它包含数亿行,有5列(long guid int bit datetimeoffset),还有其他替代方法吗?@LukeMcGregor表中当前有多少数据?感谢堆的回答,我对SQL为什么现在不选择我的索引有了更深入的理解,非常感谢