web-dev-qa-db-ja.com

COUNTクエリが結果セットクエリよりも高速なのはなぜですか?

複雑な結合を持つ2つの同様のクエリがあるとします。クエリ1は行と列を返します。

SELECT col1, col2, col3, ...etc 
FROM MyBigTable
   LEFT JOIN AnotherTable1 On ... etc 
   LEFT JOIN AnotherTable2 On ... etc
WHERE someCol1= val1
AND someCol2= val2
AND etc...

クエリ2は、クエリ1に従って行数だけを返します。

SELECT count(MyBigTable.PKcol)
FROM MyBigTable
   LEFT JOIN AnotherTable1 On ... etc 
   LEFT JOIN AnotherTable2 On ... etc
WHERE someCol1= val1
AND someCol2= val2
AND etc...

自明のロジックは、SQLエンジン(ほとんどのデータベース、たとえばSQL Server、MySQL、IBM DB2、whatevs ...)が結果セットクエリよりも速くカウントクエリからreturnになることを教えてくれます-少なくとも大きな結果セットについて話しているとき。明らかに、ネットワークを介して多数の行と列を転送するには、countの単一のスカラー値よりも時間がかかります。

私の質問は次のとおりです。

  1. DBエンジンは、両方のクエリに対して同じ量の作業/労力を実行する必要がありますか?
  2. もしそうなら、ボトルネック(または結果の受信の遅れ)は単にネットワークを介してより大きなデータを転送することによるものですか?
1
joedotnot

これは、テーブルとインデックスのレイアウト、および使用しているデータベースエンジンによって異なりますが、一般に、COUNTの例の方が高速である理由は2つあります。

1。読み取る必要のあるページが少なくなります。結合およびフィルター操作の結果のために返される必要のある行を見つけた後でも、クエリはデータページを読み取っての値を見つける必要がある場合があります。出力する追加の列。
これは常に当てはまるわけではありません。テーブルのデザインとクエリが、とにかくすべてがテーブルスキャンされるようなものである場合、2つのクエリのパフォーマンスは同じように悪くなる可能性があります。また、クラスター化インデックスをサポートするDBでは、クエリプランナーがクラスター化キーのみを使用することになった場合、それ以上の読み取りは行われない可能性があります。また、必要なすべての出力情報を見つけるために必要な作業量に同様の影響を与えるカバーインデックスがある場合があります。
DBの1つからのSQLServerのクエリプランの例を使用すると(他のDBも同様に動作します):_SELECT JobTitleId FROM Person WHERE JobTitleId = 17_は
plan for select just indexed value
必要なものをすべて見つけるために単純なインデックスを調べる必要があることを示しています。 _SELECT JobTitleId, LastName, FirstName FROM Person WHERE JobTitleId = 17_の計画は、追加の出力列に必要な追加のルックアップを示しています。
plan for select with extra columns
SELECT COUNT(*) FROM Person WHERE JobTitleId = 17の計画は、実際に行をカウントするために少し余分な作業を行う必要があることを示していますが、これは離れて余分なデータページを読み取る必要がある場合に比べて非常に小さいです。
plan for select count
それぞれの場合に_SET STATISTICS IO ON_でタッチされたページ数を確認できます。単一列とカウントの例はどちらも_logical reads 2_を示し、追加の列が出力された例は_logical reads 213_を示します。

2。転送および処理する必要のあるデータが少なくなります。これは、多くの場合、上記よりも重要ではありませんが、大規模なデータや低速の接続の場合は必ずしもそうとは限りません。エンジンがデータを見つけたら、それを呼び出し元のアプリケーションに送信する必要があります(おそらく、ローカルIPC応答経由ではなくネットワーク経由))。アプリケーションはそれを処理して表示する必要があります。COUNTクエリの結果は1つの値を持つ1つの行のみになるため、これは迅速になります。他のクエリでは、非常に多くの行がアプリケーションに転送され、アプリケーションによって処理される可能性があります。

注:説明では、例よりも単純なクエリを使用しましたが、より複雑なクエリについても考慮事項は同じです。結合、サブクエリ、およびその他の追加作業があり、再生中のオブジェクトの数が乗算される可能性があります。

2
David Spillett

正確な理由は、おそらく異なるDBMSのアーキテクチャ間で異なる可能性がありますが、主キーインデックスのスキャンは、通常、テーブル自体のスキャンよりも高速です。エンジンでの効果はネットワークでの効果と似ていると思います。エンジンの異なる領域間でシャッフルするデータが少ないほど、高速になります。

2
Lennart