Sql-Server
>= 和 > 的基數估計,用於步內統計值
我試圖了解 SQL Server 如何嘗試估計 SQL Server 2014 中的“大於”和“大於等於”where 子句。
我想我確實理解了基數估計,例如,如果我這樣做了
select * from charge where charge_dt >= '1999-10-13 10:47:38.550'
基數估計是 6672,可以很容易地計算為 32(EQ_ROWS) + 6624(RANGE_ROWS) + 16 (EQ_ROWS) = 6672(下面截圖中的直方圖)
但是當我這樣做時
select * from charge where charge_dt >= '1999-10-13 10:48:38.550'
(將時間增加到 10:48 所以它不是一個步驟)
估計是 4844.13。
那是怎麼計算的?
唯一的困難是決定如何處理查詢謂詞區間**部分覆蓋的直方圖步驟。**如問題中所述,謂詞範圍涵蓋的整個直方圖步驟是微不足道的。
傳統基數估計器
F
= 查詢謂詞所涵蓋的步長范圍的分數(介於 0 和 1 之間)。基本思想是使用
F
(線性插值)來確定謂詞覆蓋了多少步內不同值。將此結果乘以每個不同值的平均行數(假設均勻),然後將步長相等的行相加,得出基數估計:基數 = EQ_ROWS + (AVG_RANGE_ROWS * F * DISTINCT_RANGE_ROWS)
相同的公式用於
>
和>=
在舊版 CE 中。新基數估計器
新的 CE 稍微修改了之前的算法以區分
>
和>=
。首先
>
,公式為:基數 = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1)))
因為
>=
它是:基數 = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1))
這
+ 1
反映了當比較涉及相等時,假設匹配(包含假設)。在問題範例中,
F
可以計算為:DECLARE @Q datetime = '1999-10-13T10:48:38.550', @K1 datetime = '1999-10-13T10:47:38.550', @K2 datetime = '1999-10-13T10:51:19.317'; DECLARE @QR float = DATEDIFF(MILLISECOND, @Q, @K2), -- predicate range @SR float = DATEDIFF(MILLISECOND, @K1, @K2) -- whole step range SELECT F = @QR / @SR;
結果是0.728219019233034。
>=
將其代入其他已知值的公式中:基數 = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1)) = 16 + (16.1956 * ((0.728219019233034 * (409 - 1)) + 1)) = 16 + (16.1956 * ((0.728219019233034 * 408) + 1)) = 16 + (16.1956 * (297.113359847077872 + 1)) = 16 + (16.1956 * 298.113359847077872) = 16 + 4828.1247307393343837632 = 4844.1247307393343837632 = **4844.12473073933**(浮點精度)
該結果與問題中顯示的 4844.13 的估計值一致。
使用舊版 CE 的相同查詢(例如使用跟踪標誌 9481)應產生以下估計:
基數 = EQ_ROWS + (AVG_RANGE_ROWS * F * DISTINCT_RANGE_ROWS) = 16 + (16.1956 * 0.728219019233034 * 409) = 16 + 4823.72307468722 = **4839.72307468722**
>
請注意,對於和>=
使用舊版 CE ,估計值是相同的。