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?
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);1row fetched in0.0032(1.2679 seconds)SELECT COUNT(*)FROM t_inner WHERE val =1000OR val =2000OR val =3000OR val =4000OR val =5000OR val =6000OR val =7000OR val =8000OR val =9000;1row fetched in0.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.
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.
CREATETABLE 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')
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.
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).
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.
Antworten:
Ich gehe davon aus, dass Sie den Leistungsunterschied zwischen den folgenden Elementen kennen möchten:
Laut Handbuch für MySQL
IN
sortiert die Liste bei konstanten Werten die Liste und verwendet dann eine binäre Suche. Ich würde mir vorstellen, dassOR
sie einzeln in keiner bestimmten Reihenfolge bewertet werden. IstIN
also 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:
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.
quelle
IN
Methode die Optimierung einfacher macht als eine ganze Reihe möglicherweise verwandterOR
Klauseln. Ich wäre überrascht, wenn es eine Engine gibt, bei der dieOR
Methode schneller ist, aber ich bin nicht überrascht, dass es Zeiten gibt, in denen der OP langsamer ist.OR
s durch ein ersetzenIN
?Der beste Weg, dies herauszufinden, ist ein Blick auf den Ausführungsplan.
Ich habe es mit Oracle versucht und es war genau das gleiche.
Obwohl die Abfrage verwendet wird
IN
, wird im Ausführungsplan Folgendes verwendetOR
:quelle
INLIST ITERATOR
Operation, die es auswählen würde, wenn es einen Index gäbe, den es verwenden könnte. Dennoch , wenn ich es ausprobiert, beideIN
undOR
mit dem gleichen Ausführungsplan enden.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.
quelle
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
IN
eindeutig gewinnt).quelle
OR
Sinnvoll (aus Sicht der Lesbarkeit), wenn weniger Werte verglichen werden müssen.IN
ist nützlich, insb. Wenn Sie eine dynamische Quelle haben, mit der Werte verglichen werden sollen.Eine andere Alternative ist die Verwendung von a
JOIN
mit einer temporären Tabelle.Ich denke nicht, dass die Leistung ein Problem sein sollte, vorausgesetzt, Sie haben die erforderlichen Indizes.
quelle
Ich habe eine SQL-Abfrage in einer großen Anzahl von OR (350) durchgeführt. Postgres machen es 437.80ms .
Verwenden Sie jetzt IN:
23,18 ms
quelle