21

自動インクリメント整数である主キーに基づいて取得したい一連の連続した行があります。穴がないと仮定すると、以下の間にパフォーマンスはありますか?

SELECT * FROM `theTable` WHERE `id` IN (n, ... nk); 

と:

SELECT * FROM `theTable` WHERE `id` BETWEEN n AND nk;
4

4 に答える 4

17

BETWEEN この場合、特に成長し、統計がまだ正確であるため、パフォーマンスが優れているはずINです(ただし、実行計画も測定およびチェックしてください!)。n仮定しましょう:

  • mあなたのテーブルのサイズです
  • nあなたの範囲のサイズです

インデックスを使用できます (nに比べて小さいですm)

  • 理論的にBETWEENは、主キー インデックスに対して単一の「範囲スキャン」(Oracle が話す) で実装でき、その後、ほとんどのnインデックス リーフ ノードをトラバースできます。複雑さはO(n + log m)

  • INn通常、主キー インデックスに対する一連の「範囲スキャン」(ループ) として実装されます。テーブルのサイズがm大きいため、複雑さは常にO(n * log m)...常に悪化します(非常に小さなテーブルmまたは非常に小さな範囲の場合は無視できますn

インデックスは使用できません (nは のかなりの部分ですm)

いずれにせよ、テーブル全体をスキャンして、各行の述語を評価します。

  • BETWEEN2 つの述語を評価する必要があります。1 つは下限用、もう 1 つは上限用です。複雑さはO(m)

  • INnほとんどの述語を評価する必要があります。複雑さはO(m * n)...これも常に悪化するO(m)か、データベースがINリストを述語のリストではなくハッシュマップになるように最適化できる場合です。

于 2011-06-15T07:29:19.633 に答える
16

a between b and cに展開されるマクロですb <= a and a <= c

a in (b,c,d)に展開されるマクロですa=b or a=c or a=d

と が整数であると仮定するnnk、どちらも同じ意味になるはずです。バリアントの比較ではなく、2 つの比較しかないため、betweenバリアントははるかに高速になるはずです。nk - nin

于 2010-07-22T11:29:54.870 に答える
4

私はこの質問のために調査を行いました。テーブルに 1,100 万行あります。その上で2つのクエリを実行しました:

クエリ 1:SELECT * FROM PLAYERS WHERE SCORE BETWEEN 10 TO 20

クエリ 2:SELECT * FROM PLAYERS WHERE SCORE IN (10,11,...,20)

実行時に、 Andomarが上で述べたように、両方のクエリが変換されます。

両方のクエリの中で、クエリ 1 はクエリ 2 よりも高速に実行されています。

詳細については、次のリンクを参照してください。

MySQL での BETWEEN VS IN() のパフォーマンス

ありがとうございました。

于 2014-12-02T11:50:16.930 に答える