自動インクリメント整数である主キーに基づいて取得したい一連の連続した行があります。穴がないと仮定すると、以下の間にパフォーマンスはありますか?
SELECT * FROM `theTable` WHERE `id` IN (n, ... nk);
と:
SELECT * FROM `theTable` WHERE `id` BETWEEN n AND nk;
BETWEEN
この場合、特に成長し、統計がまだ正確であるため、パフォーマンスが優れているはずIN
です(ただし、実行計画も測定およびチェックしてください!)。n
仮定しましょう:
m
あなたのテーブルのサイズですn
あなたの範囲のサイズですn
に比べて小さいですm
)理論的にBETWEEN
は、主キー インデックスに対して単一の「範囲スキャン」(Oracle が話す) で実装でき、その後、ほとんどのn
インデックス リーフ ノードをトラバースできます。複雑さはO(n + log m)
IN
n
通常、主キー インデックスに対する一連の「範囲スキャン」(ループ) として実装されます。テーブルのサイズがm
大きいため、複雑さは常にO(n * log m)
...常に悪化します(非常に小さなテーブルm
または非常に小さな範囲の場合は無視できますn
)
n
は のかなりの部分ですm
)いずれにせよ、テーブル全体をスキャンして、各行の述語を評価します。
BETWEEN
2 つの述語を評価する必要があります。1 つは下限用、もう 1 つは上限用です。複雑さはO(m)
IN
n
ほとんどの述語を評価する必要があります。複雑さはO(m * n)
...これも常に悪化するO(m)
か、データベースがIN
リストを述語のリストではなくハッシュマップになるように最適化できる場合です。
a between b and c
に展開されるマクロですb <= a and a <= c
。
a in (b,c,d)
に展開されるマクロですa=b or a=c or a=d
。
と が整数であると仮定するn
とnk
、どちらも同じ意味になるはずです。バリアントの比較ではなく、2 つの比較しかないため、between
バリアントははるかに高速になるはずです。nk - n
in
私はこの質問のために調査を行いました。テーブルに 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() のパフォーマンス
ありがとうございました。