【发布时间】:2011-07-24 15:39:09
【问题描述】:
好吧,问题并不是真正“如何避免”排序,因为它是业务逻辑所要求的,而是如何使用索引初步完成,而不是在旅途中。
我有一个查询计划:
|--Sort(TOP 5, ORDER BY:([this_].[DateAdded] DESC))
|--Nested Loops(Inner Join, OUTER REFERENCES:([this_].[Id], [Expr1002]) OPTIMIZED WITH UNORDERED PREFETCH)
|--Index Seek(OBJECT:([storm].[dbo].[Items].[IX_Items_ByLocationSorted] AS [this_]), SEEK:([this_].[Status]=(1) AND [this_].[RegionId]=(32) AND [this_].[LocationId]=(32001)), WHERE:([storm].[dbo].[Items].[SubcategoryTypeId] as [this_].[SubcategoryTypeId]=(88) AND ([storm].[dbo].[Items].[IsHidden] as [this_].[IsHidden]<(1) OR [storm].[dbo].[Items].[IsHidden] as [this_].[IsHidden]>(1))) ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([storm].[dbo].[Items].[PK_Items] AS [this_]), SEEK:([this_].[Id]=[storm].[dbo].[Items].[Id] as [this_].[Id]) LOOKUP ORDERED FORWARD)
您可以看到,Index Seek 操作返回一组行。比查询优化器执行键查找来检索整行(因为无论如何他都必须返回它),然后它按 DateAdded 列对所有这些行进行排序。这是一个明显且完全有效的行为。但考虑到 Index Seek(最大 30k)返回的行数,它真的很慢(可能需要长达 40 秒)。
如何加快查询速度并尽可能避免这种移动排序?
PS:查询的表大约有300万行,并且经常更新。这可能会导致页面锁定,但我认为这些锁定不会持续 40 秒。
查询:
SELECT TOP 5 *
FROM Items
WHERE
SubcategoryTypeId = 88
and RegionId = 32
and LocationId = 32001
and not (IsHidden = 1 and Status = 1)
ORDER BY DateAdded desc
【问题讨论】:
-
当然,应该把它放在首位。我会把它添加到主帖中。
-
当您的 查询 指定
ORDER BY DateAdded DESC时,为什么要抱怨DateAdded上的排序? -
真正的问题不是如何避免排序本身,而是是否有任何方法可以不执行排序,而是依靠索引来存储已经排序的数据。
标签: sql-server sorting indexing lookup seek