簡體   English   中英

SQL Server查詢優化 - 簡單查詢中的意外緩慢

[英]SQL Server Query Optimisation - Unexpected slowness in a simple query

可能的解釋在評論中

在SQL Server 2014企業版(64位)中 - 我試圖從視圖中讀取。 標准查詢只包含這樣的ORDER BYOFFSET-FETCH子句。

方法1

SELECT

    *

FROM Metadata
ORDER BY
    AgeInHours      ASC, 
    RankingPoint    DESC, 
    PublishDate     DESC
OFFSET 150000 ROWS
FETCH NEXT 40 ROWS ONLY

但是,這個相當簡單的查詢比以下返回相同結果的查詢執行快9倍 (在跳過大量行(如150k)時顯而易見)。

在這種情況下,我首先讀取主鍵,然后將其用作WHERE...IN函數的參數

方法2

SELECT 
    * 
FROM Metadata
WHERE NewsId IN (
    SELECT

        NewsId

    FROM Metadata
    ORDER BY
        AgeInHours      ASC, 
        RankingPoint    DESC, 
        PublishDate     DESC
    OFFSET 150000 ROWS
    FETCH NEXT 40 ROWS ONLY
)
ORDER BY
    AgeInHours      ASC, 
    RankingPoint    DESC, 
    PublishDate     DESC

這兩個基准標記顯示了這種差異

(40 row(s) affected)

 SQL Server Execution Times:
   CPU time = 14748 ms,  elapsed time = 3329 ms.

(40 row(s) affected)

 SQL Server Execution Times:
   CPU time = 3828 ms,  elapsed time = 469 ms.

我在主鍵上有索引, PubilshDate和它們的碎片非常低。 我還嘗試對數據庫表運行類似的查詢,但在每種情況下,第二種方法都會產生很大的性能提升。 我也在SQL Server 2012上測試了這個。

有人可以解釋發生了什么嗎?

架構

架構

方法1:執行計划

方法1:執行計划

方法2:執行計划(左側部分)

方法2:執行計划(左側部分)

方法2:執行計划(右側部分)

方法2:執行計划(右側部分)

對於具有相同結果集的不同結構化查詢,您將獲得具有不同方法和查詢成本的不同查詢計划。 這對於各種SQL RDBMS實現來說很常見。

基本上在上面的示例中,從大表中選擇小部分數據時,首先要減少和最小化結果中的行數,然后選擇包含所有列的完整行,就像2.查詢一樣。

另一種方法是在第一步中為減少結果集建立精確的適當索引。 在上面的查詢中,可能是來自同一列和排序順序的ORDER BY子句中的列可以是一個解決方案。

(您沒有發送查詢計划中提到的索引結構,我可以想象隱藏在其名稱后面的內容。)

您還可以使用SQL索引提示將SQL優化器定向到您認為最適合任務的特定索引,以防SQL優化器不執行此任務。

執行查詢時,引擎會查找可用於獲得最佳性能的索引。 您的方法1使用的索引不包括SELECT語句中的所有列,這會導致查詢計划中的Key Lookup,根據我的經驗,這總是得到較低的性能,只使用SELECT語句中的索引列。

如果為AgeInHours, RankingPoint, PublishDate和INCLUDE創建所有列的索引(建議僅用於測試目的) AgeInHours, RankingPoint, PublishDate您可以看到差異。

對於第二種方法,如果使用CTE然后使用IN進行JOIN而不是WHERE,或者如果您有數百萬行則使用索引創建臨時表,則甚至可以獲得更好的性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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