目前資料表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 = @id
select * 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是另外的開銷是另一回事)