0

私は最近、私の経験に基づいてこの質問に答えました:

実際の検索に進む前に行をカウントする

しかし、私が出した答えに 100% 満足しているわけではありません。

COUNT問題は基本的に次のとおりです。実際の行を戻すクエリを実行することを決定する前に、特定のクエリを実行することでパフォーマンスを向上させることはできますか?

私の直感は次のとおりです。データをカウントするには、実際に行を見つける必要があるため、カウントではなく、データの取得に関連する I/O とワイヤ時間のみを節約できます。これに対する例外として考えられるのは、クエリがインデックスの単純な関数である場合です。

私の質問は次のとおりです。これは常に真ですか? 他にどのような例外ケースがありますか? COUNT純粋なパフォーマンスの観点から、完全なクエリを実行 する前に、どのような場合に実行したいですか?

4

1 に答える 1

1

まず、あなたの質問に対する答えは、データベースに大きく依存しています。

クエリの前に COUNT() を実行すると、クエリと count() の両方の全体的な時間が短縮される状況は考えられません。

一般に、カウントを実行すると、テーブルとインデックスがページ キャッシュに事前に読み込まれます。データがメモリに収まると仮定すると、これにより後続のクエリの実行が高速になります (ただし、I/O が高速で、データベースが先読みページ読み取りを行う場合はそれほど高速ではありません)。ただし、全体の時間を短縮するのではなく、時間枠を COUNT() にシフトしただけです。

全体の時間 (COUNT() の実行時間を含む) を短縮するには、実行計画を変更する必要があります。これが理論的に発生する可能性のある 2 つの方法を次に示します。

  1. テーブルが読み込まれると、データベースは統計を更新でき、これらの統計はメイン クエリのクエリ プランを変更します。
  2. データベースは、テーブル/インデックスが既にページ キャッシュにあるかどうかに基づいて実行計画を変更できます。

理論的には可能ですが、これらのいずれかを実行するデータベースは知りません。

中間結果を保存できると想像できますが、これは SQL データベースの動的な性質に違反します。つまり、COUNT() とクエリの間のテーブルで更新/挿入が発生する可能性があります。データベース エンジンは整合性を維持できず、そのような中間結果を維持できませんでした。

COUNT() を実行すると、後続のクエリの高速化に比べて不利な点があります。COUNT() のクエリ プランは、メイン クエリのクエリ プランとはかなり異なる場合があります。インデックスを使用した例は 1 つのケースです。もう 1 つのケースは、データのさまざまな垂直パーティションを読み取る必要がない列データベースです。

さらに別のケースは、次のようなクエリです。

select t.*, r.val
from table t left outer join
     ref r
     on t.refID = r.refID

refID は、ref テーブルの一意のインデックスです。重複がなく、t 内のすべてのレコードが使用されるため、この結合はカウントのために削除できます。ただし、このクエリには明らかに結合が必要です。繰り返しになりますが、SQL オプティマイザがこの状況を認識して対処するかどうかは、完全にデータベースの作成者の決定です。ただし、結合は理論的には COUNT() に対して最適化することができます。

于 2012-07-25T18:01:20.520 に答える