162

別の会社から継承したアプリケーションの遅いセクションをリファクタリングして、次のようなサブクエリの代わりに内部結合を使用しました。

WHERE id IN (SELECT id FROM ...)

リファクタリングされたクエリは、約 100 倍速く実行されます。(約 50 秒から約 0.3 秒) 改善を期待していましたが、なぜ劇的な改善になったのか説明できる人はいますか? where 句で使用される列はすべてインデックス化されています。SQL は、行ごとに 1 回、where 句でクエリを実行しますか?

更新- 結果の説明:

違いは、「where id in ()」クエリの 2 番目の部分にあります。

2   DEPENDENT SUBQUERY  submission_tags ref st_tag_id   st_tag_id   4   const   2966    Using where

vs 結合を含む 1 つのインデックス付き行:

    SIMPLE  s   eq_ref  PRIMARY PRIMARY 4   newsladder_production.st.submission_id  1   Using index
4

14 に答える 14

161

「相関サブクエリ」 (つまり、where 条件が含まれるクエリの行から取得された値に依存するサブクエリ) は、行ごとに 1 回実行されます。非相関サブクエリ (where 条件が含まれるクエリから独立しているサブクエリ) は、最初に 1 回実行されます。SQL エンジンは、この区別を自動的に行います。

しかし、ええ、explain-plan は汚い詳細を提供します。

于 2008-09-26T19:03:42.213 に答える
38

結合はインデックスで行われますが、すべての行に対してサブクエリを 1 回実行しています。

于 2008-09-26T19:01:12.123 に答える
16

MySQL 6.0 でサブクエリがどのように評価されるかの例を次に示します。

新しいオプティマイザは、この種のサブクエリを結合に変換します。

于 2008-09-28T07:19:08.910 に答える
7

各バージョンで Explain-plan を実行すると、その理由がわかります。

于 2008-09-26T19:00:10.207 に答える
6

クエリがクエリ オプティマイザに渡されたデータセットに対して実行される前に、オプティマイザは結果セットから可能な限り多くのタプル (行) をできるだけ早く削除できるようにクエリを編成しようとします。多くの場合、サブクエリ (特に悪いもの) を使用すると、外側のクエリの実行が開始されるまで、結果セットからタプルをプルーニングできません。

クエリを確認しないと、元のクエリのどこが悪かったのかを判断するのは困難ですが、私の推測では、オプティマイザが改善できなかったものであると思われます。「explain」を実行すると、データを取得するためのオプティマイザー メソッドが表示されます。

于 2008-09-26T19:06:24.437 に答える
4

where サブクエリは、返された行ごとに 1 つのクエリを実行する必要があります。内部結合は 1 つのクエリを実行するだけです。

于 2008-09-26T19:18:32.677 に答える
4

各クエリのクエリ プランを確認します。

Where inJoin通常、同じ実行プランを使用して実装できるため、通常、それらの間の変更によるスピードアップはありません。

于 2008-09-26T19:01:05.917 に答える
4

オプティマイザーはあまり良い仕事をしませんでした。通常、それらは何の違いもなく変換でき、オプティマイザーはこれを行うことができます。

于 2008-09-26T19:01:34.293 に答える
4

通常、サブクエリを結合として実行できることをオプティマイザが判断できない結果です。この場合、クエリしているテーブルに対してサブクエリ内のテーブルを結合するのではなく、テーブル内の各レコードに対してサブクエリを実行します。より「エンタープライズ」なデータベースの一部はこれに優れていますが、それでも時々見逃します。

于 2008-09-26T19:03:02.090 に答える
4

この質問はやや一般的であるため、一般的な回答は次のとおりです。

基本的に、MySQL でソートする行が大量にある場合、クエリの時間が長くなります。

これを行う:

各クエリ (JOIN されたもの、次にサブクエリされたもの) で EXPLAIN を実行し、結果をここに投稿します。

これらのクエリに対する MySQL の解釈の違いを見ることは、誰にとっても学習経験になると思います。

于 2008-09-26T19:05:45.390 に答える
3

サブクエリが「フル テーブル スキャン」を実行していた可能性があります。つまり、インデックスを使用せず、Where from メイン クエリで除外する必要がある行が多すぎます。

もちろん、詳細のない単なる推測ですが、それは一般的な状況です。

于 2008-09-26T19:02:58.733 に答える
2

サブクエリでは、結果ごとに 2 番目の SELECT を再実行する必要があり、各実行は通常 1 行を返します。

結合を使用すると、2 番目の SELECT はより多くの行を返しますが、実行する必要があるのは 1 回だけです。利点は、結果に結合できるようになったことです。リレーションの結合は、データベースが得意とすることです。たとえば、オプティマイザはインデックスをより有効に活用する方法を見つけられるかもしれません。

于 2008-09-26T19:02:04.790 に答える
2

結合は、少なくとも Oracle の SQL エンジンの基盤であり、非常に高速に実行されますが、IN 句ほどサブクエリではありません。

于 2008-09-26T19:02:52.057 に答える
2

リファレンス マニュアルから抜粋 ( 14.2.10.11 Rewriting Subqueries as Joins ):

LEFT [OUTER] JOIN は、サーバーがより適切に最適化できる可能性があるため、同等のサブクエリよりも高速になる可能性があります (これは MySQL サーバーだけに固有の事実ではありません)。

そのため、サブクエリは LEFT [OUTER] JOINS よりも遅くなる可能性があります。

于 2016-09-20T13:34:42.480 に答える