sql >> データベース >  >> RDS >> Sqlserver

なぜこれはインデックス スキャンであり、インデックス シークではないのですか?

    マージ結合も使用しているため、主にインデックス スキャンを使用しています。 Merge Join オペレーターには、結合条件と互換性のある順序でソートされた 2 つの入力ストリームが必要です。

    また、Merge Join 演算子を使用して INNER JOIN を実現しています。これは、より一般的な Nested Loop Join 演算子よりも高速であると考えているためです。おそらく正しいでしょう (通常はそうです)、選択した 2 つのインデックスを使用することで、結合条件 (LocationID) に従って両方とも事前に並べ替えられた入力ストリームを持ちます。入力ストリームがこのように事前に並べ替えられている場合、ほとんどの場合、マージ結合は他の 2 つ (ループおよびハッシュ結合) よりも高速です。

    マイナス面は、あなたが気づいたことです:インデックス全体をスキャンしているように見えます.その答えは、スキャンは (シーケンシャルな性質のため) シークの 1 秒あたり 10 倍から 100 倍のレコードを読み取ることができるということです。

    シークは選択的であるため、通常は勝ちます。要求した行のみを取得しますが、スキャンは非選択的です。範囲内のすべての行を返す必要があります。しかし、スキャンには 多くの 読み取り率が高く、破棄された行と一致する行の比率が低い限り、頻繁にシークを打ち負かすことができます スキャン行/秒 VS の比率よりも。行/秒をシークします。

    質問がありますか?

    OK、最後の文をもっと説明するように頼まれました:

    「破棄された行」とは、スキャンが読み取ったもの (インデックス内のすべてを読み取る必要があるため) ですが、反対側に一致がないため、Merge Join オペレーターによって拒否されます。 WHERE 句の条件によって既に除外されています。

    「一致する行」とは、Merge Join 内の何かと実際に一致するものを読み取ったものです。これらは、Scan が Seek に置き換えられた場合に Seek によって読み取られるのと同じ行です。

    クエリ プランの統計を見ると、何があるかを把握できます。 Index Scan の左側にある太い矢印が見えますか?これは、オプティマイザーがスキャンで読み取ると考える行数を表します。投稿したインデックス スキャンの統計ボックスには、実際に返された行数が約 5.4M (5,394,402) であることが示されています。これは次と同じです:

    TotalScanRows = (MatchingRows + DiscardedRows)
      

    (とにかく、私の言葉で)。一致する行を取得するには、Merge Join オペレーターによって報告される「実際の行」を調べます (これを正確に取得するには、TOP 100 を削除する必要がある場合があります)。これがわかれば、次の方法で破棄された行を取得できます。

    DiscardedRows = (TotalScanRows - MatchingRows)
      

    これで比率を計算できます。



    1. MySQLSETデータ型をPostgresに変換します

    2. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:

    3. Docker Compose and Postgres:名前が解決されない

    4. テーブルを適切に切り捨てるにはどうすればよいですか?