當通過 USE PLAN 提示或通過儲存的查詢計劃提供時,為什麼 SQL Server 2012 不使用我的“更好”執行計劃?
我有一個我無法更改的第 3 方應用程序,它執行一個“錯誤”的選擇查詢,在某些情況下執行速度非常慢(我們有時會在 6 小時後將其殺死)。這是在我們盡我們所能通過索引加速它之後,這是我們可以控制的。
SELECT * FROM findetail WHERE fintransact is null and (validation is null or validation <= ' ' or validation = ' Zero value transaction;') and (exists (select * from counterparty where counterparty.counterparty = findetail.counterparty and counterparty.status = 'ACTIVE') or findetail.counterparty is null) and (findetail.acctstatus = 'FINAL' or findetail.acctstatus = 'PROVISIONAL') and (findetail.transactiontype = 'AP' or findetail.transactiontype = 'AR') and ((findetail.position not in (select position.position from position where position.positionmode = 'FINANCIAL' and position.exchange is not null) ) or (findetail.fee in (select fee from fee, feetype where findetail.fee = fee.fee and fee.feetype = feetype.feetype and feetype.excludemargin = 1 ) ) ) and ( findetail.counterparty = 'ACPTY' )
將查詢重寫為至少有點“更好”是很容易的:
SELECT * FROM findetail WHERE fintransact is null and (validation is null or validation <= ' ' or validation = ' Zero value transaction;') and (exists (select * from counterparty where counterparty.counterparty = findetail.counterparty and counterparty.status = 'ACTIVE') or findetail.counterparty is null) and (findetail.acctstatus = 'FINAL' or findetail.acctstatus = 'PROVISIONAL') and (findetail.transactiontype = 'AP' or findetail.transactiontype = 'AR') and (not exists (select position.position from position where position.positionmode = 'FINANCIAL' and position.exchange is not null and position = findetail.position) or exists (select fee from fee, feetype where findetail.fee = fee.fee and fee.feetype = feetype.feetype and feetype.excludemargin = 1 and findetail.fee = fee) ) AND ( findetail.counterparty = 'ACPTY' )
這仍然不是完美的最佳選擇,但執行時間約為 8 秒,這比幾個小時要好得多。它還保留了原始的粗略結構格式,這很重要,因為最後的選擇是嘗試編輯查詢字元串(它是可見的,但由於它是使用程式碼中的一些“if”語句動態建構的,所以它被分成幾個部分)在第三方應用程序的 .dll 之一中。
旁白:當我使用正確的連接完全重寫查詢以“更好”(低至 3 秒執行時間)時,當我嘗試時,SQL 伺服器將不再將這個“更好”的執行計劃辨識為對“壞”查詢有效通過 USE PLAN 查詢提示使用它。另外,如果我最終嘗試將其編輯回 .dll 是不可能的。
因此,我擷取了“更好”查詢的執行計劃,並嘗試使用 USE PLAN 提示將其強制執行“壞”查詢。SQL Server 接受強制計劃為有效(至少,不會像“更好”的計劃那樣抱怨),但它實際上也沒有使用“更好”的計劃。顯示估計的執行計劃顯示了與以前相同的錯誤計劃,並且在我殺死它之前,實際執行導致查詢執行至少 10 分鐘。
我已經在 SSMS 中嘗試了這個,最後有一個 USE PLAN 提示,並通過創建一個儲存的查詢計劃。無論哪種方式,SQL Server 在執行查詢時都會繼續使用“壞”計劃。關於為什麼如果它認為該計劃是有效的它仍然沒有使用它的任何想法?
任何幫助表示讚賞,謝謝!
為了回答的目的,我們將它們標記為查詢 A 和查詢 B。查詢 A 和查詢 B 不相同(即使它們產生相同的結果)。
當要求 SQL 執行查詢 A 時,不能強制 SQL 使用為查詢 B 生成的計劃。
USE PLAN 用於在單個查詢存在多個計劃時執行特定計劃。 https://www.brentozar.com/archive/2018/03/why-multiple-plans-for-one-query-are-bad/
Rob,這是哨兵計劃探索者的計劃: