SQL Serverのオプティマイザーは、結合されたテーブルの行数をどのように推定しますか?


13

AdventureWorks2012データベースでこのクエリを実行しています。

SELECT 
    s.SalesOrderID,
    d.CarrierTrackingNumber,
    d.ProductID,
    d.OrderQty
FROM Sales.SalesOrderHeader s 
JOIN Sales.SalesOrderDetail d 
    ON s.SalesOrderID = d.SalesOrderID
WHERE s.CustomerID = 11077

推定実行計画を見ると、次のことがわかります。

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

最初のインデックスシーク(右上)はIX_SalesOrderHeader_CustomerIDインデックスを使用し、リテラル11077で検索しています。推定推定値は2.6192行です。

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

を使用するDBCC SHOW_STATISTICS ('Sales.SalesOrderHeader', 'IX_SalesOrderHeader_CustomerID') WITH HISTOGRAMと、値11077が2つのサンプリングされたキー11019と11091の間にあることがわかります。

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

11019から11091までの個別の行の平均数は2.619718であり、2.61972に丸められます。これは、インデックスシークで表示される推定行の値です。

私が理解していない部分は、SalesOrderDetailテーブルに対するクラスター化インデックスシークの推定行数です。

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

私が実行した場合DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail', 'PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID')

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

したがって、SalesOrderID(私が参加している)の密度は3.178134E-05です。これは、1 / 3.178134E-05(31465)がSalesOrderDetailテーブルの一意のSalesOrderID値の数に等しいことを意味します。

SalesOrderDetailに31465個の一意のSalesOrderIDがあり、均等に分布している場合、SalesOrderIDあたりの平均行数は121317(行の総数)を31465で割った値です。平均は3.85561です。

したがって、ループスルーの推定行数が2.61972で、平均が3.85561で返される場合、推定行数は2.61972 * 3.85561 = 10.10062になると思います。

ただし、推定行数は11.4867です。

2番目の推定値の私の理解は間違っていると思います。異なる数字はそれを示しているようです。私は何が欠けていますか?

回答:


20

2番目の推定値の私の理解は間違っていると思います。異なる数字はそれを示しているようです。私は何が欠けていますか?

SQL Server 2012カーディナリティ推定器を使用すると、結合の選択性により、ネストされたループ結合の内側の推定行数が決まります。

11.4867の数値は、計算された結合出力の推定カーディナリティ(30.0919)を反復回数(2.61972)で除算することにより(ショープランでの表示用に)導出されます。単精度浮動小数点演算を使用した結果は11.4867です。

本当に簡単です。(論理)結合の選択性は、物理結合演算子の選択とは無関係であることに注意してください。最終的にネストされたループ、ハッシュ、または結合の物理演算子を使用して結合が実行されるかどうかは同じです。

SQL Server 2012以前では、結合選択性(全体として)はSalesOrderID、各テーブルのヒストグラムを使用して推定されます(必要に応じて線形補間を使用したステップ境界調整後、各ヒストグラムステップで計算されます)。SalesOrderID関連付けられたヒストグラムSalesOrderHeaderテーブルはまた、独立のスケーリング効果のために調整されているCustomerIDフィルタ。

それは、質問で提案された代替計算に根本的に「間違った」何かがあるということではありません。それは異なる仮定のセットを作るだけです。論理演算の特定のシーケンスの推定値を計算または結合するには、常にさまざまな方法があります。同じデータに異なる統計手法を適用しても同じ回答が得られる、または一方の手法が他方の手法よりも常に優れているという一般的な保証はありません。さまざまな統計手法を適用した結果生じる不整合は、ほとんど気付かれることはありませんが、1つの最終的な実行計画内に現れることさえあります。

補足として、SQL Server 2014のカーディナリティ推定器は、独立したフィルターで調整されたヒストグラム情報(「粗調整」)を結合するための異なるアプローチを採用しており、このクエリでは10.1006行の異なる最終推定が得られます。

Plan for computation:

  CSelCalcExpressionComparedToExpression
  (QCOL: [s].SalesOrderID x_cmpEq QCOL: [d].SalesOrderID)

Loaded histogram for column QCOL: [s].SalesOrderID from stats with id 1
Loaded histogram for column QCOL: [d].SalesOrderID from stats with id 1

Stats collection generated: 

  CStCollJoin(ID=4, **CARD=10.1006** x_jtInner)
      CStCollFilter(ID=3, CARD=2.61972)
          CStCollBaseTable(ID=1, CARD=31465 TBL: Sales.SalesOrderHeader AS TBL: s)
      CStCollBaseTable(ID=2, CARD=121317 TBL: Sales.SalesOrderDetail AS TBL: d)

これは問題の計算と同じ結果になりますが、詳細な推論は異なります(つまり、想定されるネストされたループの実装に基づいていません)。

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