最適化の記事の一部と、次のステートメントのsegfaultedを読みました。
OR
とUNION
を使用してSQL置換ステートメントを使用する場合:select username from users where company = ‘bbc’ or company = ‘iTV’;
に:
select username from users where company = ‘bbc’ union select username from users where company = ‘iTV’;
クイックEXPLAIN
から:
OR
を使用:
UNION
を使用:
これは、UNION
が作業の2倍で行うことを意味しませんか?
UNION
は特定のRDBMSと特定のテーブルスキーマのパフォーマンスが向上する可能性があることに感謝していますが、これはcategorically trueではありません。
私が間違っている?
あなたが読んだ記事が悪い例を使用したか、あなたが彼らの主張を誤解したかのどちらかです。
select username from users where company = 'bbc' or company = 'iTV';
これは次と同等です:
select username from users where company IN ('bbc', 'iTV');
MySQLは、このクエリに対してcompany
のインデックスをうまく使用できます。 UNIONを実行する必要はありません。
よりトリッキーなケースは、2つのdifferent列を含むOR
条件がある場合です。
select username from users where company = 'bbc' or city = 'London';
company
にインデックスがあり、city
に別のインデックスがあるとします。 MySQLは通常、指定されたクエリのテーブルごとに1つのインデックスのみを使用するため、どのインデックスを使用する必要がありますか? company
のインデックスを使用する場合、city
がロンドンである行を見つけるためにテーブルスキャンを行う必要があります。 city
のインデックスを使用する場合、company
がbbcである行に対してテーブルスキャンを実行する必要があります。
UNION
ソリューションは、このタイプのケース用です。
select username from users where company = 'bbc'
union
select username from users where city = 'London';
これで、各サブクエリは検索にインデックスを使用でき、サブクエリの結果はUNION
によって結合されます。
匿名ユーザーが上記の私の回答の編集を提案しましたが、モデレーターが編集を拒否しました。編集ではなくコメントである必要があります。提案された編集の主張は、UNIONが結果セットをソートして重複行を排除する必要があるというものでした。これにより、クエリの実行が遅くなるため、インデックスの最適化に時間がかかります。
私の応答は、UNIONが発生する前に、インデックスが結果セットを少数の行に減らすのに役立つということです。 UNIONは実際に重複を排除しますが、それを行うには小さな結果セットをソートするだけです。 WHERE句がテーブルの重要な部分と一致する場合があり、UNION中のソートは、単にテーブルスキャンを実行するのと同じくらい高価です。しかし、インデックス付き検索によって結果セットが削減されるのがより一般的であるため、ソートはテーブルスキャンよりもはるかに低コストです。
違いは、テーブル内のデータと検索対象の用語によって異なります。特定のクエリに最適なソリューションを決定する唯一の方法は、両方のメソッドを MySQLクエリプロファイラ で試し、パフォーマンスを比較することです。
これらは同じクエリではありません。
私はMySQLの経験があまりないので、クエリオプティマイザーが何をするかしないかわかりませんが、ここに私の一般的な背景(主にms SQLサーバー)からの私の考えを示します。
通常、クエリアナライザーは上記の2つのクエリを取得し、それらからまったく同じ計画を作成できます(それらが同じ場合)。これらのクエリ(同等)の間にパフォーマンスの違いはないと思われます。
select distinct username from users where company = ‘bbc’ or company = ‘iTV’;
そして
select username from users where company = ‘bbc’
union
select username from users where company = ‘iTV’;
さて、問題は、実際にはわかりませんが、次のクエリには違いがありますが、オプティマイザは最初のクエリのようにすると思われます
select username from users where company = ‘bbc’ or company = ‘iTV’;
そして
select username from users where company = ‘bbc’
union all
select username from users where company = ‘iTV’;
これは、データのサイズ、インデックス、ソフトウェアバージョンなどに基づいてオプティマイザーが実行する処理に依存します。
ORを使用すると、すべてが単一の論理ステートメント内にあるため、オプティマイザーが効率を見つける可能性が高くなると思います。
また、UNIONには、リセットset(重複なし)が作成されるため、オーバーヘッドがあります。 companyがインデックス付けされている場合、UNIONの各ステートメントは非常に高速に実行されるはずです...実際に実行されているかどうかわからないdouble作品。
クエリからすべての速度を絞る必要が本当にない限り、意図を最もよく伝えるフォームを使用することをお勧めします... OR
INについても言及しました。次のクエリは、OR(これも私が好む形式です)よりも優れたパフォーマンスを提供すると信じています。
select username from users where company in ('bbc', 'iTV');