it-swarm.com.de

Unterabfragen mit EXISTS vs IN - MySQL

Unter zwei Abfragen befinden sich Unterabfragen. Beide sind gleich und funktionieren gut für mich. Das Problem ist jedoch, dass die Abfrage der Methode 1 etwa 10 Sekunden dauert, während die Abfrage der Methode 2 weniger als 1 Sekunde dauert.

Ich konnte Methode 1-Abfrage in Methode 2 konvertieren, verstehe aber nicht, was in der Abfrage passiert. Ich habe versucht, es selbst herauszufinden. Ich möchte wirklich gerne wissen, was der Unterschied zwischen zwei Abfragen ist und wie die Leistungssteigerung erfolgt. Was ist die Logik dahinter?

Ich bin neu bei diesen fortgeschrittenen Techniken. Ich hoffe, dass mir hier jemand helfen wird. Angenommen, ich lese die docs , die mir keinen Hinweis geben.

Methode 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 
         )
   )

Methode 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
         )                                             
   )
20
Techie

Ein Explain Plan hätte Ihnen gezeigt, warum genau Sie Exists verwenden sollten. Normalerweise kommt die Frage Exists vs Count(*). Exists ist schneller. Warum?

  • In Bezug auf die durch NULL vorliegenden Herausforderungen: Wenn subquery Null zurückgibt, wird für IN die gesamte Abfrage Null. Also musst du auch damit umgehen. Bei Verwendung von Exist handelt es sich jedoch lediglich um eine false. Viel leichter zu bewältigen. Einfach IN kann nichts mit Null vergleichen, aber Exists kann.

  • z.B. Exists (Select * from yourtable where bla = 'blabla'); erhalten Sie wahr/falsch, wenn ein Treffer gefunden wird

  • In diesem Fall nimmt IN die Position von Count(*) ein, um ALL übereinstimmende Zeilen basierend auf der WHERE auszuwählen, da alle Werte verglichen werden. 

Aber vergiss das auch nicht:

  • EXISTS wird mit hoher Geschwindigkeit gegen IN ausgeführt: wenn das Ergebnis der Unterabfrage sehr groß ist.
  • IN kommt EXISTS voraus: wenn das Ergebnis der Unterabfrage sehr klein ist.

Verweis auf für weitere Details:

46
bonCodigo

Methode 2 ist schnell, da sie den Operator EXISTS verwendet, bei dem ich MySQL keine Ergebnisse lade . Wie in Ihrem docs -Link erwähnt, werden die in SELECT enthaltenen Klauseln weggelassen. Es wird nur nach dem ersten Wert gesucht, der den Kriterien entspricht. Sobald er gefunden wurde, wird die Bedingung TRUE festgelegt und zur weiteren Verarbeitung verschoben. 

Auf der anderen Seite hat Methode 1 einen IN-Operator, der alle möglichen Werte lädt und dann mit diesen übereinstimmt. Die Bedingung wird TRUE nur festgelegt, wenn eine exakte Übereinstimmung gefunden wird, was einen zeitaufwendigen Prozess darstellt.

Daher ist deine Methode 2 schnell.

Ich hoffe es hilft... 

3
Shubhansh

Der Operator EXISTS ist ein boolescher Operator, der entweder true oder false zurückgibt. Der EXISTS-Operator wird häufig in einer Unterabfrage verwendet, um die Bedingung "exist" zu testen.

SELECT 
    select_list
FROM
    a_table
WHERE
    [NOT] EXISTS(subquery);

Wenn die Unterabfrage eine Zeile zurückgibt, gibt der Operator EXISTS true zurück, andernfalls false.

Außerdem beendet der Operator EXISTS die Weiterverarbeitung sofort, sobald er eine passende Zeile findet. Aufgrund dieses Merkmals können Sie den Operator EXISTS verwenden, um in einigen Fällen die Leistung der Abfrage zu verbessern.

Der Operator NOT negiert den Operator EXISTS. Mit anderen Worten: NOT EXISTS gibt true zurück, wenn die Unterabfrage keine Zeile zurückgibt, andernfalls false.

Sie können SELECT *, SELECT-Spalte, SELECT a_constant oder irgendetwas in der Unterabfrage verwenden. Die Ergebnisse sind die gleichen, da MySQL die select_list ignoriert, die in der Klausel SELECT angezeigt wird.

Der Grund dafür ist, dass der Operator EXISTS nach dem Prinzip „zumindest gefunden“ arbeitet. Es gibt true zurück und stoppt den Scanvorgang, sobald mindestens eine übereinstimmende Zeile gefunden wurde.

Wenn dagegen der Operator IN mit einer Unterabfrage kombiniert wird, muss MySQL die Unterabfrage zuerst verarbeiten und verwendet dann das Ergebnis der Unterabfrage, um die gesamte Abfrage zu verarbeiten.

Als Faustregel gilt: Wenn die Unterabfrage eine große Datenmenge enthält, bietet der Operator EXISTS eine bessere Leistung.

Die Abfrage, die den Operator IN verwendet, wird jedoch schneller ausgeführt, wenn die von der Unterabfrage zurückgegebene Ergebnismenge sehr klein ist.

Für detaillierte Erklärungen und Beispiele: MySQL EXISTS - mysqltutorial.org

1
ktnam

Die zweite Methode ist schneller, weil Sie dies wie "WHERE t3.reservation_id = t.reservation_id" haben. Im ersten Fall muss Ihre Unterabfrage zur Überprüfung der Informationen einen vollständigen Scan in die Tabelle durchführen. Bei der 2o-Methode weiß die Unterabfrage jedoch genau, wonach sie sucht, und sobald sie gefunden ist, wird die Bedingung dann geprüft. 

0
medina