Sql-Server

使用聲明的變數時估計的行非常錯誤

  • April 17, 2016

我對此查詢的聚集索引查找步驟的估計非常**非常錯誤(估計行數為 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 文章

引用自:https://dba.stackexchange.com/questions/84626