Sql-Server
為什麼添加 TOP 1 會顯著降低性能?
我有一個相當簡單的查詢
SELECT TOP 1 dc.DOCUMENT_ID, dc.COPIES, dc.REQUESTOR, dc.D_ID, cj.FILE_NUMBER FROM DOCUMENT_QUEUE dc JOIN CORRESPONDENCE_JOURNAL cj ON dc.DOCUMENT_ID = cj.DOCUMENT_ID WHERE dc.QUEUE_DATE <= GETDATE() AND dc.PRINT_LOCATION = 2 ORDER BY cj.FILE_NUMBER
這給了我可怕的表現(就像從不費心等待它完成一樣)。查詢計劃如下所示:
但是,如果我刪除它,
TOP 1
我會得到一個看起來像這樣的計劃,它會在 1-2 秒內執行:正確的 PK 和索引如下。
更改查詢計劃這一事實
TOP 1
並不讓我感到驚訝,我只是有點驚訝它使它變得更糟。注意:我已經閱讀了這篇文章的結果並理解了 a
Row Goal
等的概念。我很好奇的是如何更改查詢以使其使用更好的計劃。目前我正在將數據轉儲到臨時表中,然後將第一行從中拉出。我想知道是否有更好的方法。編輯對於事後閱讀本文的人來說,這裡有一些額外的資訊。
- Document_Queue - PK/CI 是 D_ID,它有大約 5k 行。
- Correspondence_Journal - PK/CI 是 FILE_NUMBER、CORRESPONDENCE_ID,它有大約 140 萬行。
當我開始時沒有其他索引。我最終在 Correspondence_Journal (Document_Id, File_Number) 上找到了一個
嘗試強制雜湊連接*
SELECT TOP 1 dc.DOCUMENT_ID, dc.COPIES, dc.REQUESTOR, dc.D_ID, cj.FILE_NUMBER FROM DOCUMENT_QUEUE dc INNER HASH JOIN CORRESPONDENCE_JOURNAL cj ON dc.DOCUMENT_ID = cj.DOCUMENT_ID AND dc.QUEUE_DATE <= GETDATE() AND dc.PRINT_LOCATION = 2 ORDER BY cj.FILE_NUMBER
優化器可能認為循環使用 top 1 會更好,這是有道理的,但實際上它在這裡不起作用。這裡只是一個猜測,但可能該閥芯的估計成本已關閉 - 它使用 TEMPDB - 您可能有一個性能不佳的 TEMPDB。
- 小心連接提示,因為它們強制計劃表訪問順序與查詢中表的寫入順序相匹配(就像
OPTION (FORCE ORDER)
已指定一樣)。從文件連結:這在範例中可能不會產生任何不良影響,但總的來說,它很有可能。
FORCE ORDER
(隱含的或顯式的)是一個非常強大的提示,超出了執行命令的範圍;它阻止應用廣泛的優化器技術,包括部分聚合和重新排序。在合適的情況下,
OPTION (HASH JOIN)
查詢提示的侵入性可能較小,因為這並不意味著FORCE ORDER
. 但是,它確實適用於查詢中的所有聯接。其他解決方案可用。