25

以下の 2 つのクエリはサブクエリです。どちらも同じで、どちらも私にとってはうまくいきます。ただし、問題は、方法 1 のクエリの実行に約 10 秒かかるのに対し、方法 2 のクエリの実行には 1 秒もかかりません。

方法 1 のクエリを方法 2 に変換できましたが、クエリで何が起こっているのかわかりません。私はそれを自分で理解しようとしてきました。以下の2つのクエリの違いと、パフォーマンスの向上はどのように起こるのかを本当に知りたいですか? その背後にあるロジックは何ですか?

私はこれらの高度な技術に不慣れです。誰かがここで私を助けてくれることを願っています。手がかりを与えないドキュメントを読んだことを考えると。

方法 1 :

SELECT
   *       
FROM
   tracker       
WHERE
   reservation_id IN (
      SELECT
         reservation_id                                 
      FROM
         tracker                                 
      GROUP  BY
         reservation_id                                 
      HAVING
         (
            method = 1                                          
            AND type = 0                                          
            AND Count(*) > 1 
         )                                         
         OR (
            method = 1                                              
            AND type = 1                                              
            AND Count(*) > 1 
         )                                         
         OR (
            method = 2                                              
            AND type = 2                                              
            AND Count(*) > 0 
         )                                         
         OR (
            method = 3                                              
            AND type = 0                                              
            AND Count(*) > 0 
         )                                         
         OR (
            method = 3                                              
            AND type = 1                                              
            AND Count(*) > 1 
         )                                         
         OR (
            method = 3                                              
            AND type = 3                                              
            AND Count(*) > 0 
         )
   )

方法 2 :

SELECT
   *                                
FROM
   `tracker` t                                
WHERE
   EXISTS (
      SELECT
         reservation_id                                              
      FROM
         `tracker` t3                                              
      WHERE
         t3.reservation_id = t.reservation_id                                              
      GROUP BY
         reservation_id                                              
      HAVING
         (
            METHOD = 1 
            AND TYPE = 0 
            AND COUNT(*) > 1
         ) 
         OR                                                     
         (
            METHOD = 1 
            AND TYPE = 1 
            AND COUNT(*) > 1
         ) 
         OR                                                    
         (
            METHOD = 2 
            AND TYPE = 2 
            AND COUNT(*) > 0
         ) 
         OR                                                     
         (
            METHOD = 3 
            AND TYPE = 0 
            AND COUNT(*) > 0
         ) 
         OR                                                     
         (
            METHOD = 3 
            AND TYPE = 1 
            AND COUNT(*) > 1
         ) 
         OR                                                     
         (
            METHOD = 3 
            AND TYPE = 3 
            AND COUNT(*) > 0
         )                                             
   )
4

5 に答える 5

56

AnExplain Planは、正確に を使用する必要がある理由を示していますExists。通常、質問が来Exists vs Count(*)ます。 Existsより高速です。なんで?

  • NULL によって提示される課題に関して:サブクエリが を返すNull場合、IN の場合、クエリ全体が になりNullます。したがって、それも処理する必要があります。しかし、を使用するExistと、それは単なるfalse. はるかに簡単に対処できます。単にIN何も比較することはできませんNullが、Existsできます。

  • たとえば、 1 つのヒットが見つかった/一致しExists (Select * from yourtable where bla = 'blabla');た瞬間に true/false を取得します。

  • この場合、並べ替えは、すべての値を比較しているため、に基づいて一致するすべての行を選択するためINにの位置を取ります。Count(*)WHERE

ただし、次のことも忘れないでください。

  • EXISTSINサブクエリの結果が非常に大きい場合、 :に対して高速に実行されます。
  • INEXISTSサブクエリの結果が非常に小さい場合: の前に取得します。

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

于 2013-01-07T10:55:42.640 に答える
4

方法 2 は、結果をロードしないEXISTS演算子を使用しているため高速です。ドキュメントのリンクにもMySQL記載されているように、句にあるものはすべて省略されています。条件に一致する最初の値のみをチェックし、見つかったら条件を設定して、さらに処理を進めます。SELECTTRUE

一方、メソッド1にはIN、可能なすべての値をロードしてから一致させる演算子があります。完全一致が見つかった場合にのみ条件が設定されTRUEますが、これは時間のかかるプロセスです。

したがって、方法2は高速です。

それが役に立てば幸い...

于 2013-01-07T06:14:40.587 に答える
0

2 番目の方法は、"WHERE t3.reservation_id = t.reservation_id" のようになっているため高速です。最初のケースでは、情報を確認するために、サブクエリでテーブルをフル スキャンする必要があります。ただし、2o メソッドでは、サブクエリは探しているものを正確に認識しており、サブクエリが見つかると、所有条件がチェックされます。

于 2013-01-07T07:36:00.277 に答える
-3

彼らの公式ドキュメント。Exists を使用したサブクエリの最適化

于 2014-04-15T14:12:23.893 に答える