簡體   English   中英

ORDER BY索引列仍然很慢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM