自動インクリメント整数である主キーに基づいて取得したい一連の連続した行があります。穴がないと仮定すると、以下の間にパフォーマンスはありますか?
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)
INn通常、主キー インデックスに対する一連の「範囲スキャン」(ループ) として実装されます。テーブルのサイズがm大きいため、複雑さは常にO(n * log m)...常に悪化します(非常に小さなテーブルmまたは非常に小さな範囲の場合は無視できますn)
nは のかなりの部分ですm)いずれにせよ、テーブル全体をスキャンして、各行の述語を評価します。
BETWEEN2 つの述語を評価する必要があります。1 つは下限用、もう 1 つは上限用です。複雑さはO(m)
INnほとんどの述語を評価する必要があります。複雑さは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 - nin
私はこの質問のために調査を行いました。テーブルに 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() のパフォーマンス
ありがとうございました。