[英]SQL Server Query Optimisation - Unexpected slowness in a simple query
可能的解釋在評論中
在SQL Server 2014企業版(64位)中 - 我試圖從視圖中讀取。 標准查詢只包含這樣的ORDER BY
和OFFSET-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:執行計划
方法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.