为什么选择顶部...按索引列排序仍然会进行排序?

8
我创建了以下索引来覆盖选择顶部语句。
-- Column A, B have type of int
create unique index ix_ on T (A, B) with (data_compression = page) 
-- tried to create non-unique index too and the execution plan is the same

select top 20 A, B from T order by A, B -- 19 seconds
select top 20 A, B from T -- return result instantly

然而,它仍需要一段时间(我的表有5000万行,需要19秒),执行计划显示仍然有一个“排序”操作?
执行计划如下:

1
我不确定,但是唯一索引并不能提高性能,我认为你需要一个普通索引。 - GuidoG
你确定索引的创建顺序与“order by”中的键相同,并且没有其他键吗? - Gordon Linoff
2
获取快速和慢速查询的实际执行计划的XML,并将其包含在问题中。如果XML太大,请使用pastebin.com或类似的工具。 - Vladimir Baranov
1
包括实际执行计划。您的描述缺少一些内容。 - Martin Smith
1
@MartinSmith 是的。这就是为什么创建了索引 ix_ 来覆盖查询的原因。 - ca9163d9
显示剩余12条评论
1个回答

5

你的表按B进行分区。

除非你另有指定,否则索引将继承这种分区方案。例如:

create unique index ix_ on T (A, B)  with (data_compression = page) on [primary] 

如果出现这种情况,它将变得不对齐,并阻止一些操作,例如仅元数据切换。

最小的“A”值可能在任何一个分区中。

这个并没有被优化得很好。您可以保留对齐的索引并使用此重写 基于此处的代码

SELECT TOP 20 A, B 
FROM sys.partitions AS P
  CROSS APPLY ( SELECT TOP 20 A, B 
                FROM dbo.T
                WHERE $PARTITION.YourPartitionFunction(T.B) = P.partition_number 
                ORDER BY A,B
                ) AS A
WHERE P.object_id = OBJECT_ID('dbo.T')
AND P.index_id = INDEXPROPERTY( OBJECT_ID('dbo.T'), 'ix_', 'IndexID' )
ORDER BY  A,B

它将从41个分区中获取每个分区的前20行(不进行排序),然后仅对结果中的820行进行排序,以获得最终的前20行(而不是整个4200万行)。


但是索引 ix_ 没有分区,而查询使用了该索引吗? - ca9163d9
2
@dc7a9163d9 - 索引已分区。请在您的计划中查看 PartitionsAccessed PartitionCount="41"。- 如果未指定 partition_scheme_name 或 filegroup 并且表已分区,则索引将放置在相同的分区方案中,使用与底层表相同的分区列。 - Martin Smith
除了元数据开关之外,创建额外的非对齐索引还有其他缺点吗?谢谢。 - ca9163d9
1
@dc7a9163d9 - 能够快速切换分区是我使用分区的唯一原因。所以这对我来说是一个重要问题。我从未使用过非对齐索引,因此不确定您是否会遇到其他问题。我建议保持索引对齐并使用解决方法。 - Martin Smith
1
我只想指出这很棒。 - Gordon Linoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接