我有以下查询,<使用ORDER BY b.Price
时为1,使用ORDER BY b.Price DESC
时为10秒
select * from
(
select
/* When changed to ORDER BY b.Price DESC it's 10x slower! */
(row_number() over (ORDER BY b.Price)) as RowNumber,
b.*
from
Books b (nolock)
inner join BookPublishRegions p (nolock)
on b.BookKey = bp.BookKey
where
contains(p.PublishRegionName, 'France')
) as t1
where t1.RowNumber between 100 and 110
对于为什么有任何想法?
我在b.Price
上有一个升序和降序索引。我不确定我还能在这做什么......
作为参考,我包括以下两个索引的CREATE脚本:
CREATE NONCLUSTERED INDEX [IX_Books_PriceDesc] ON [dbo].[Books]
(
[Price] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_Books_Price] ON [dbo].[Books]
(
[Price] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
答案 0 :(得分:2)
正如另一位用户所提到的,如果没有查看查询计划,那就是疯狂的猜测。但如果查询在任何一种情况下都使用索引,我会感到惊讶。即使它们覆盖索引,你在子查询中过滤窗口函数的结果,规划器也无法知道row_number函数将返回100-110哪些行,直到它解析了整个结果集。子查询,您实际上还没有按价格对子查询进行排序,因此使用任一索引都没有任何好处。我无法解释为什么在这些条件下上升的情况会更快,但是我们必须看到一个查询计划来解决这个问题,但我怀疑还有其他的东西可能会起作用。
看起来你正在使用窗口函数来实现分页,如果是这样,并且你使用的是2012或更高版本,请尝试使用offset / fetch,例如:
select
b.*
from
Books b (nolock)
inner join BookPublishRegions p (nolock)
on b.BookKey = bp.BookKey
where
contains(p.PublishRegionName, 'France')
order by price desc
offset 100 fetch 10
计划者可能会意识到它可以使用索引。虽然它可能需要成为聚集或覆盖索引才能说实话。
如果你是在2008年或更早的时候,请尝试在子查询中按顺序排列显示顺序,以便规划人员意识到它可以使用索引。您仍然可以使用窗口函数并在外部查询中进行过滤来进行分页,但这样可以在很少的行上运行窗口函数:
select * from
(
select top 110
(row_number() over (ORDER BY b.Price DESC)) as RowNumber,
b.*
from
Books b (nolock)
inner join BookPublishRegions p (nolock)
on b.BookKey = bp.BookKey
where
contains(p.PublishRegionName, 'France')
ORDER BY b.Price DESC
) as t1
where t1.RowNumber between 100 and 110
答案 1 :(得分:0)
我会查看SSMS中的估计查询计划(Ctrl + L)。我怀疑它没有使用任何一个索引,因为它们没有覆盖。
此外,在较慢的降序选项的情况下,它引入了另一个排序选项,因为数据可能已经排序到选定的连接策略。
不看实际的查询计划,这只是疯狂的猜测
答案 2 :(得分:0)
您是否尝试过按降序使用升序索引?根据这篇文章,它应该以这样的方式快速地执行,以便具有升序索引和升序,并且消除了对降序索引的需要。自快速实验以来值得一试。 Building SQL Server Indexes in Ascending vs Descending Order
答案 3 :(得分:0)
我会尝试将索引编码到Select语句中。由于您已预定义索引。
语法是
With (NOLOCK, Index(Index_Name))
答案 4 :(得分:0)
两种情况都使用您提到的索引吗?或者是使用另一个索引的ASC示例,该索引不需要对“。*”选择进行键查找。