IN vs OR in der SQL WHERE-Klausel

150

Welche Leistung ist beim Umgang mit großen Datenbanken besser INoder ORin der SQL- WhereKlausel?

Gibt es einen Unterschied in der Art und Weise, wie sie ausgeführt werden?

felix
quelle
Meine erste Vermutung wäre, dass OR eine bessere Leistung erbringt, es sei denn, die SQL-Engine konvertiert IN hinter den Kulissen in OR. Haben Sie den Abfrageplan dieser beiden gesehen?
Raj
Mögliches Duplikat der Leistung
Steve Chambers

Antworten:

170

Ich gehe davon aus, dass Sie den Leistungsunterschied zwischen den folgenden Elementen kennen möchten:

WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'

Laut Handbuch für MySQLIN sortiert die Liste bei konstanten Werten die Liste und verwendet dann eine binäre Suche. Ich würde mir vorstellen, dass ORsie einzeln in keiner bestimmten Reihenfolge bewertet werden. Ist INalso unter Umständen schneller.

Der beste Weg, dies zu wissen, besteht darin, beide in Ihrer Datenbank mit Ihren spezifischen Daten zu profilieren, um festzustellen, welche schneller sind.

Ich habe beide auf einem MySQL mit 1000000 Zeilen ausprobiert. Wenn die Spalte indiziert ist, ist kein Leistungsunterschied erkennbar - beide sind nahezu augenblicklich. Wenn die Spalte nicht indiziert ist, habe ich folgende Ergebnisse erhalten:

SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);
1 row fetched in 0.0032 (1.2679 seconds)

SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000;
1 row fetched in 0.0026 (1.7385 seconds)

In diesem Fall ist die Methode mit OR etwa 30% langsamer. Das Hinzufügen weiterer Begriffe macht den Unterschied größer. Die Ergebnisse können in anderen Datenbanken und in anderen Daten variieren.

Mark Byers
quelle
20
Wenn der Optimierer sein Salz wert ist, sollte er dasselbe tun.
Janick Bernet
27
@inflagranti: Leider ist kein Optimierer perfekt. Optimierer sind äußerst komplexe Programme, und jede Implementierung hat ihre eigenen Stärken und Schwächen. Aus diesem Grund sollten Sie sich zu einer bestimmten Implementierung profilieren. Ich würde mir vorstellen, dass die zusätzliche Struktur der INMethode die Optimierung einfacher macht als eine ganze Reihe möglicherweise verwandter ORKlauseln. Ich wäre überrascht, wenn es eine Engine gibt, bei der die ORMethode schneller ist, aber ich bin nicht überrascht, dass es Zeiten gibt, in denen der OP langsamer ist.
Mark Byers
2
@MarkByers Konnte der Optimierer nicht immer mehrere ORs durch ein ersetzen IN?
Tymtam
36

Der beste Weg, dies herauszufinden, ist ein Blick auf den Ausführungsplan.


Ich habe es mit Oracle versucht und es war genau das gleiche.

CREATE TABLE performance_test AS ( SELECT * FROM dba_objects );

SELECT * FROM performance_test
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB' );

Obwohl die Abfrage verwendet wird IN, wird im Ausführungsplan Folgendes verwendet OR:

--------------------------------------------------------------------------------------    
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time     |    
--------------------------------------------------------------------------------------    
|   0 | SELECT STATEMENT  |                  |     8 |  1416 |   163   (2)| 00:00:02 |    
|*  1 |  TABLE ACCESS FULL| PERFORMANCE_TEST |     8 |  1416 |   163   (2)| 00:00:02 |    
--------------------------------------------------------------------------------------    

Predicate Information (identified by operation id):                                       
---------------------------------------------------                                       

   1 - filter("OBJECT_NAME"='DBMS_LOB' OR "OBJECT_NAME"='DBMS_REGISTRY' OR                
              "OBJECT_NAME"='DBMS_STANDARD')                                              
Peter Lang
quelle
1
Was passiert in Oracle, wenn Sie mehr als 3 Werte testen? Wissen Sie, ob Oracle nicht in der Lage ist, dieselbe binäre Suchoptimierung wie MySQL durchzuführen, oder führt es diese in beiden Fällen durch?
Mark Byers
2
@ Mark Byers: Ich habe die gleiche Abfrage mit 10 Werten versucht, immer noch das gleiche Ergebnis. Beachten Sie, dass der Optimierer meine Werte in alphabetischer Reihenfolge neu sortiert hat. Es würde mich nicht wundern, wenn Oracle diesen Filter intern optimieren würde ...
Peter Lang
5
Oracle hat auch eine INLIST ITERATOROperation, die es auswählen würde, wenn es einen Index gäbe, den es verwenden könnte. Dennoch , wenn ich es ausprobiert, beide INund ORmit dem gleichen Ausführungsplan enden.
Cheran Shunmugavel
7

Der OR-Operator benötigt einen viel komplexeren Bewertungsprozess als das IN-Konstrukt, da er viele Bedingungen zulässt, die nicht nur gleich IN sind.

Hier ist ein Beispiel dafür, was Sie mit OR verwenden können, das jedoch nicht mit IN kompatibel ist: größer. größer oder gleich, kleiner, kleiner oder gleich, LIKE und einige mehr wie das Orakel REGEXP_LIKE. Beachten Sie außerdem, dass die Bedingungen möglicherweise nicht immer den gleichen Wert vergleichen.

Für das Abfrageoptimierungsprogramm ist es einfacher, den IN-Operator zu verwalten, da es sich nur um ein Konstrukt handelt, das den OR-Operator unter mehreren Bedingungen mit dem Operator = auf demselben Wert definiert. Wenn Sie den Operator OR verwenden, berücksichtigt das Optimierungsprogramm möglicherweise nicht, dass Sie den Operator = immer für denselben Wert verwenden. Wenn keine tiefere und sehr viel komplexere Ausarbeitung durchgeführt wird, kann dies wahrscheinlich ausschließen, dass nur dieser Operator vorhanden ist = Operatoren für die gleichen Werte unter allen beteiligten Bedingungen, mit dem konsequenten Ausschluss optimierter Suchmethoden wie der bereits erwähnten binären Suche.

[BEARBEITEN] Wahrscheinlich implementiert ein Optimierer möglicherweise keinen optimierten IN-Evaluierungsprozess, dies schließt jedoch nicht aus, dass dies einmal passieren könnte (mit einem Upgrade der Datenbankversion). Wenn Sie also den OR-Operator verwenden, wird die optimierte Ausarbeitung in Ihrem Fall nicht verwendet.

Alessandro Rossi
quelle
6

Ich denke, Orakel ist klug genug, um das weniger effiziente (was auch immer das ist) in das andere umzuwandeln. Daher denke ich, dass die Antwort eher von der Lesbarkeit jedes einzelnen abhängen sollte (wo ich denke, dass dies INeindeutig gewinnt).

Soulmerge
quelle
2

ORSinnvoll (aus Sicht der Lesbarkeit), wenn weniger Werte verglichen werden müssen. INist nützlich, insb. Wenn Sie eine dynamische Quelle haben, mit der Werte verglichen werden sollen.

Eine andere Alternative ist die Verwendung von a JOINmit einer temporären Tabelle.
Ich denke nicht, dass die Leistung ein Problem sein sollte, vorausgesetzt, Sie haben die erforderlichen Indizes.

shahkalpesh
quelle
-2

Ich habe eine SQL-Abfrage in einer großen Anzahl von OR (350) durchgeführt. Postgres machen es 437.80ms .

Verwenden Sie OR

Verwenden Sie jetzt IN:

Verwenden Sie IN

23,18 ms

user3003962
quelle
4
Das ist nicht ganz dasselbe, da Sie eine Unterabfrage für die IN-Klausel verwendet haben.
Gliljas