Sql-Server
使用聲明的變數時估計的行非常錯誤
我對此查詢的聚集索引查找步驟的估計非常**非常錯誤(估計行數為 8,637,530;實際為 74,723):
Declare @StartDate as date = '10/1/2014'; Declare @EndDate as date = '10/2/2014'; select Sum(Quantity) from Daily_GC_Items where SalesDate between @StartDate and @EndDate;
如果我對這樣的日期使用字元串文字,估計幾乎是完美的(估計行數為 75,337.4;實際為 74,723):
select Sum(Quantity) from Daily_GC_Items where SalesDate between '10/1/2014' and '10/2/2014'
表定義:
[SalesDate] [date] NOT NULL, [Store] [varchar](10) NOT NULL, [GuestCheckNumber] [smallint] NOT NULL, [ItemSequence] [smallint] NOT NULL, [Quantity] [smallint] NOT NULL, (Several more columns)
首要的關鍵:
[SalesDate] ASC, [Store] ASC, [GuestCheckNumber] ASC, [ItemSequence] ASC
這種行為的可能原因是什麼?
…SSMS 沒有使用 sp_execute 執行它,所以我認為這不是由參數嗅探引起的。這種行為的可能原因是什麼?
優化器無法“嗅探”局部變數的值,因此基數估計是基於猜測。如果您使用原始基數估計器,則固定猜測
BETWEEN
是表基數的 9%。如果使用新的基數估計器,則使用指數退避計算猜測值,並將其應用於速記的分離
>=
和<=
比較。和BETWEEN
的猜測是 30% (0.3),所以總體猜測是。>=``<=``0.3 * SQRT(0.3) = 0.164317 (* table cardinality)
您必須在記憶體和重用所有未來變數值的合理計劃之間做出決定,或者在每次執行時重新編譯以每次為特定值生成新計劃。第二個選項利用了參數嵌入優化,它僅在您使用查詢提示時應用
OPTION (RECOMPILE)
。這裡有一個明顯的權衡,在每次重新編譯的成本(生成的計劃永遠不會被記憶體以供重用)和為每次執行使用不是非常優化的重用計劃之間。您還可以考慮其他選項,包括在
OPTIMIZE FOR
提示中指定典型值;有關詳細資訊,請參閱我的SQLPerformance.com 文章。