> =および>のカーディナリティ推定(ステップ内統計値)


9

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です。

それはどのように計算されますか?

回答:


9

唯一の困難は、クエリ述語間隔で部分的にカバーされているヒストグラムステップの処理方法を決定することです。述語の範囲でカバーされる全体のヒストグラムステップは、質問で述べたように取るに足らないものです。

従来のカーディナリティエスティメータ

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を使用。


4

フィルターが「より大きい」または「より小さい」場合、行を推定する式は少し間抜けになりますが、これは到達可能な数値です。

数字

ステップ193を使用して、関連する番号は次のとおりです。

RANGE_ROWS = 6624

EQ_ROWS = 16

AVG_RANGE_ROWS = 16.1956

前のステップのRANGE_HI_KEY = 1999-10-13 10:47:38.550

現在のステップのRANGE_HI_KEY = 1999-10-13 10:51:19.317

WHERE句の値= 1999-10-13 10:48:38.550

1)2つの範囲のhiキー間のmsを見つける

SELECT DATEDIFF (ms, '1999-10-13 10:47:38.550', '1999-10-13 10:51:19.317')

結果は220767ミリ秒です。

2)行数を調整する

ミリ秒あたりの行を見つける必要がありますが、その前に、RANGE_ROWSからAVG_RANGE_ROWSを減算する必要があります。

6624-16.1956 = 6607.8044行

3)調整された行数でミリ秒あたりの行数を計算します。

6607.8044行/ 220767 ms = .0299311行/ ms

4)WHERE句の値と現在のステップRANGE_HI_KEYの間のmsを計算します

SELECT DATEDIFF (ms, '1999-10-13 10:48:38.550', '1999-10-13 10:51:19.317')

これにより160767 msが得られます。

5)1秒あたりの行数に基づいて、このステップの行を計算します。

.0299311行/ ms * 160767 ms = 4811.9332行

6)以前にAVG_RANGE_ROWSをどのように差し引いたか覚えていますか?それらを元に戻す時間です。1秒あたりの行数に関連する数値の計算が完了したので、EQ_ROWSも安全に追加できます。

4811.9332 + 16.1956 + 16 = 4844.1288

切り上げ、それは私たちの4844.13の見積もりです。

数式をテストする

ミリ秒あたりの行数が計算される前にAVG_RANGE_ROWSが差し引かれる理由に関する記事やブログ投稿は見つかりませんでした。私それらが推定で説明されていることを確認できましたが、文字通り最後のミリ秒でのみです。

WideWorldImportersデータベースを使用して、いくつかのインクリメンタルテストを行ったところ、1x AVG_RANGE_ROWSが突然含まれるステップの最後まで、行推定値の減少は線形であることがわかりました。

これが私のサンプルクエリです:

SELECT PickingCompletedWhen
FROM Sales.Orders
WHERE PickingCompletedWhen >= '2016-05-24 11:00:01.000000'

PickingCompletedWhenの統計を更新してから、ヒストグラムを取得しました。

DBCC SHOW_STATISTICS([sales.orders], '_WA_Sys_0000000E_44CA3770')

_WA_Sys_0000000E_44CA3770のヒストグラム(最後の3ステップ)

RANGE_HI_KEYに近づくにつれて推定行がどのように減少するかを確認するために、ステップ全体でサンプルを収集しました。減少は直線的ですが、AVG_RANGE_ROWS値に等しい行数がトレンドの一部ではないかのように動作します... RANGE_HI_KEYに到達し、突然、回収されていない借金のように減少します。これはサンプルデータ、特にグラフで確認できます。

ここに画像の説明を入力してください

RANGE_HI_KEYに到達するまで行が着実に減少し、最後のAVG_RANGE_ROWSチャンクであるBOOMが突然差し引かれていることに注意してください。グラフで見つけるのも簡単です。

ここに画像の説明を入力してください

要約すると、AVG_RANGE_ROWSの奇妙な扱いは行推定の計算をより複雑にしますが、CEが何をしているかを常に調整することができます。

指数バックオフはどうですか?

指数バックオフは、新しい(SQL Server 2014現在の)Cardinality Estimatorが複数の単一列統計を使用する場合に、より良い推定を取得するために使用する方法です。この質問は単一列の統計に関するものだったので、EBの式は含まれていません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.