Моим первым предположением будет то, что OR работает лучше, если только механизм SQL не преобразует IN в OR за сценой. Вы видели план запроса этих двух?
Я предполагаю, что вы хотите знать разницу в производительности между следующими:
WHERE foo IN('a','b','c')WHERE foo ='a'OR foo ='b'OR foo ='c'
Согласно руководству по MySQL, если значения постоянны, INсортирует список и затем использует двоичный поиск. Я полагаю, что ORоценивает их один за другим в произвольном порядке. Так INбыстрее в некоторых обстоятельствах.
Лучший способ узнать это - профилировать обе базы данных с вашими конкретными данными, чтобы увидеть, что быстрее.
Я пробовал оба на MySQL с 1000000 строк. Когда столбец индексируется, нет заметной разницы в производительности - оба практически мгновенные. Когда столбец не проиндексирован, я получил следующие результаты:
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)
Таким образом, в этом случае метод с использованием ИЛИ примерно на 30% медленнее. Добавление большего количества терминов увеличивает разницу. Результаты могут отличаться для других баз данных и других данных.
Если оптимизатор стоит своей соли, он должен выполнить то же самое.
Яник Бернет
27
@inflagranti: К сожалению, оптимизатор не идеален. Оптимизаторы - чрезвычайно сложные программы, и каждая реализация будет иметь свои сильные и слабые стороны. Вот почему я говорю, что вы должны описать конкретную реализацию. Я полагаю, что дополнительная структура INметода облегчает его оптимизацию, чем целый набор возможных связанных ORпредложений. Я был бы удивлен, если есть двигатель, где ORметод быстрее, но я не удивлен, что бывают случаи, когда ИЛИ медленнее.
Марк Байерс
2
@MarkByers Не может ли оптимизатор всегда заменить несколько ORs на IN?
тымтам
36
Лучший способ узнать это - посмотреть на План выполнения.
Я попробовал это с Oracle , и это было точно так же.
CREATETABLE performance_test AS(SELECT*FROM dba_objects );SELECT*FROM performance_test
WHERE object_name IN('DBMS_STANDARD','DBMS_REGISTRY','DBMS_LOB');
Несмотря на то, что запрос использует IN, план выполнения говорит, что он использует 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')
Что происходит в Oracle, если у вас есть более 3 значений, которые вы тестируете? Знаете ли вы, если Oracle не может выполнить такую же оптимизацию бинарного поиска, как MySQL, или она выполняет ее в обоих случаях?
Марк Байерс
2
@Mark Byers: я попробовал тот же запрос с 10 значениями, но результат тот же. Обратите внимание, что оптимизатор пересчитал мои значения в алфавитном порядке. Я бы не удивился, если бы Oracle провела внутреннюю оптимизацию этого фильтра ...
Питер Лэнг,
5
У Oracle также есть INLIST ITERATORоперация, которую он выбирает, если существует индекс, который он может использовать. Тем не менее, когда я попробовал, оба INи в ORконечном итоге с тем же планом выполнения.
Cheran Shunmugavel
7
Оператору OR требуется гораздо более сложный процесс оценки, чем конструкции IN, поскольку он допускает множество условий, не только равных, как IN.
Вот пример того, что вы можете использовать с ИЛИ, но которые не совместимы с IN: больше. больше или равно, меньше, меньше или равно, LIKE, а некоторые больше похожи на оракула REGEXP_LIKE. Кроме того, учтите, что условия не всегда могут сравнивать одно и то же значение.
Для оптимизатора запросов проще управлять оператором IN, потому что это только конструкция, которая определяет оператор OR для нескольких условий с оператором = для одного и того же значения. Если вы используете оператор ИЛИ, оптимизатор может не учитывать, что вы всегда используете оператор = для одного и того же значения, и, если он не выполняет более глубокую и гораздо более сложную разработку, он, вероятно, может исключить, что может быть только = операторы для одинаковых значений во всех задействованных условиях с последующим исключением оптимизированных методов поиска, таких как уже упомянутый двоичный поиск.
[EDIT] Вероятно, оптимизатор может не реализовать оптимизированный процесс оценки IN, но это не исключает, что это может произойти один раз (с обновлением версии базы данных). Так что если вы используете оператор ИЛИ, то оптимизированная разработка не будет использоваться в вашем случае.
Я думаю, что оракул достаточно умен, чтобы преобразовать менее эффективный (какой бы он ни был) в другой. Поэтому я думаю, что ответ должен скорее зависеть от читабельности каждого (где я думаю, что INявно выигрывает)
ORимеет смысл (с точки зрения читабельности), когда сравнивается меньше значений.
INполезно особенно когда у вас есть динамический источник, с которым вы хотите сравнить значения.
Другая альтернатива - использовать JOINвременную таблицу.
Я не думаю, что производительность должна быть проблемой, если у вас есть необходимые индексы.
Ответы:
Я предполагаю, что вы хотите знать разницу в производительности между следующими:
Согласно руководству по MySQL, если значения постоянны,
IN
сортирует список и затем использует двоичный поиск. Я полагаю, чтоOR
оценивает их один за другим в произвольном порядке. ТакIN
быстрее в некоторых обстоятельствах.Лучший способ узнать это - профилировать обе базы данных с вашими конкретными данными, чтобы увидеть, что быстрее.
Я пробовал оба на MySQL с 1000000 строк. Когда столбец индексируется, нет заметной разницы в производительности - оба практически мгновенные. Когда столбец не проиндексирован, я получил следующие результаты:
Таким образом, в этом случае метод с использованием ИЛИ примерно на 30% медленнее. Добавление большего количества терминов увеличивает разницу. Результаты могут отличаться для других баз данных и других данных.
источник
IN
метода облегчает его оптимизацию, чем целый набор возможных связанныхOR
предложений. Я был бы удивлен, если есть двигатель, гдеOR
метод быстрее, но я не удивлен, что бывают случаи, когда ИЛИ медленнее.OR
s наIN
?Лучший способ узнать это - посмотреть на План выполнения.
Я попробовал это с Oracle , и это было точно так же.
Несмотря на то, что запрос использует
IN
, план выполнения говорит, что он используетOR
:источник
INLIST ITERATOR
операция, которую он выбирает, если существует индекс, который он может использовать. Тем не менее, когда я попробовал, обаIN
и вOR
конечном итоге с тем же планом выполнения.Оператору OR требуется гораздо более сложный процесс оценки, чем конструкции IN, поскольку он допускает множество условий, не только равных, как IN.
Вот пример того, что вы можете использовать с ИЛИ, но которые не совместимы с IN: больше. больше или равно, меньше, меньше или равно, LIKE, а некоторые больше похожи на оракула REGEXP_LIKE. Кроме того, учтите, что условия не всегда могут сравнивать одно и то же значение.
Для оптимизатора запросов проще управлять оператором IN, потому что это только конструкция, которая определяет оператор OR для нескольких условий с оператором = для одного и того же значения. Если вы используете оператор ИЛИ, оптимизатор может не учитывать, что вы всегда используете оператор = для одного и того же значения, и, если он не выполняет более глубокую и гораздо более сложную разработку, он, вероятно, может исключить, что может быть только = операторы для одинаковых значений во всех задействованных условиях с последующим исключением оптимизированных методов поиска, таких как уже упомянутый двоичный поиск.
[EDIT] Вероятно, оптимизатор может не реализовать оптимизированный процесс оценки IN, но это не исключает, что это может произойти один раз (с обновлением версии базы данных). Так что если вы используете оператор ИЛИ, то оптимизированная разработка не будет использоваться в вашем случае.
источник
Я думаю, что оракул достаточно умен, чтобы преобразовать менее эффективный (какой бы он ни был) в другой. Поэтому я думаю, что ответ должен скорее зависеть от читабельности каждого (где я думаю, что
IN
явно выигрывает)источник
OR
имеет смысл (с точки зрения читабельности), когда сравнивается меньше значений.IN
полезно особенно когда у вас есть динамический источник, с которым вы хотите сравнить значения.Другая альтернатива - использовать
JOIN
временную таблицу.Я не думаю, что производительность должна быть проблемой, если у вас есть необходимые индексы.
источник
Я сделал запрос SQL в большом количестве ИЛИ (350). Postgres делает это 437.80мс .
Теперь используйте IN:
23.18ms
источник