[英]ORDER BY indexed column is still slow
我有以下查詢,當使用ORDER BY b.Price
時需要<1s,當使用ORDER BY b.Price DESC
時需要10s以上
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]
正如另一位用戶所提到的,如果沒有查看查詢計划,那就是瘋狂的猜測。 但如果查詢在任何一種情況下都使用索引,我會感到驚訝。 即使它們覆蓋索引,你在子查詢中過濾窗口函數的結果,規划器也無法知道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
我會看一下SSMS中的估計查詢計划(Ctrl + L)。 我懷疑它沒有使用任何一個索引,因為它們沒有覆蓋。
此外,在較慢的降序選項的情況下,它引入了另一個排序選項,因為數據可能已經排序到選定的連接策略。
不看實際的查詢計划,這只是瘋狂的推測
您是否嘗試過按降序使用升序索引? 根據這篇文章,它應該以這樣的方式快速地執行,以便具有升序索引和升序,並且消除了對降序索引的需要。 自快速實驗以來值得一試。 以升序和降序構建SQL Server索引
我會嘗試將索引編碼到Select語句中。 由於您已預定義索引。
語法是
With (NOLOCK, Index(Index_Name))
請在SELECT sql查詢之前添加“explain”來檢索查詢計划。 它將回答是否根本使用索引來評估查詢的問題。
兩個場景都使用您提到的索引嗎? 或者是使用另一個索引的ASC示例,該索引不需要對“。*”選擇進行鍵查找。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.