目前資料表A中,裡面有7百多萬的資料,且已針對該欄位建立索引
在MS SQL中,我寫了兩段寫法
SELECT TOP 10000 * FROM 資料表A WHERE 欄位1>='20240313' AND 欄位1<='20240313'
DECLARE @DATES CHAR(8)
SET @DATES = '20240313'
SELECT TOP 10000
*
FROM 資料表A
WHERE 欄位1>=@DATES AND 欄位1<=@DATES
然而我將SQL改成
DECLARE @DATES CHAR(8)
SET @DATES = '20240313'
SELECT TOP 10000
*
FROM 資料表A
WHERE 欄位1>=@DATES AND 欄位1<=@DATES
OPTION(RECOMPILE)
想詢問各位大大,這個原因是如何產生的?為何加了OPTION(RECOMPILE)卻可以改善此問題?
(如上述資訊量不夠,還煩請告知)
依據neofancy的貼文,所以有去看執行計畫的確有差異嗎?
如果的確有差異,那問題就在什麼導致SQL判斷有差異,可能原因有
參數嗅探 Parameter Sniffing 導致使用到不是較優的執行計劃
統計資料 : SQL會使用統計資料來建立可改善查詢效能的查詢計劃,所以更新資料表的統計資料試試 EXEC sp_updatestats
https://learn.microsoft.com/zh-tw/sql/relational-databases/statistics/statistics?view=sql-server-ver16
報告,這個有試過【EXEC sp_updatestats】,但是查詢的結果跟上面描述的一樣。
那應該就是參數嗅探的問題了,你可以GOOGLE一些大神前輩的處理方式
有找到另外兩篇文章,裡面所述有點像是有無帶參數而影響,如同厚厚所言,然而加上OPTION(RECOMPILE)之後,會重新編譯,執行上會等同於不帶參數的模式,所以會比較快
https://www.cnblogs.com/wy123/p/6262800.html
https://sqlperformance.com/2013/08/t-sql-queries/parameter-sniffing-embedding-and-the-recompile-options
提供參考
基本上每個 Query 下提供的條件其實應該不同,
但執行第一次查詢時,
Query engine 會產生第一個條 Query Plane,
並且針對你首次查詢時所下的條件內容作優化,
但問題來了,
你接下來的每次查詢他都會套用第一次查詢產生出來的 Query Plane,
也就是說不再針對你新的查詢請求再重新作一次優化的參數,
但你加上 OPTION(RECOMPILE) 時,
因為要重新 Compile,
所以 Query Engine 會再產生一個全新適用你此次查詢的優化參數,
因此會特別快
OPTION(RECOMPILE)是重新編譯你的語句,但要記得,重新編譯SQL語句本身也是會產生開銷的
重新編譯後,你可以理解為預處理
舉個例子好了select * from xxx where id = @idselect * from xxx where id = 1
這是帶參數跟不帶參數的,@id執行週期需要做其他處理,最後才會與select * from xxx where id =結合產生執行語句
而select * from xxx where id = 1,這件事情是不用在執行週期完成就可以產生的執行語句select * from xxx where id = @id OPTION(RECOMPILE)則是在編譯期就轉成像select * from xxx where id = 1語句
簡單來說 就是編譯期完成了執行期要做的事情(當然,recompiler是另外的開銷是另一回事)