При работе с большими базами данных, которые работают лучше, IN
или OR
в SQL Where
-clause?
Есть ли разница в том, как они выполняются?
При работе с большими базами данных, которые работают лучше, IN
или OR
в SQL Where
-clause?
Есть ли разница в том, как они выполняются?
Я предполагаю, что вы хотите узнать разницу в производительности между следующими:
WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'
В соответствии с manual for MySQL, если значения являются постоянными IN
сортирует список, а затем использует двоичный поиск. Я бы предположил, что OR
оценивает их один за другим в определенном порядке. Поэтому IN
быстрее в некоторых случаях.
Лучший способ узнать, как профилировать как в вашей базе данных ваши конкретные данные, чтобы увидеть, что быстрее.
Я пробовал как в MySQL с 1000000 строк. Когда колонка индексируется, нет заметной разницы в производительности - обе они почти мгновенные. Когда столбец не проиндексирован, я получил следующие результаты:
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)
Таким образом, в этом случае метод с использованием OR примерно на 30% медленнее. Добавление большего количества терминов делает разницу больше. Результаты могут отличаться в других базах данных и других данных.
Лучший способ узнать - это план выполнения.
Я попробовал его с Oracle, и он был точно таким же.
CREATE TABLE 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')
Я думаю, что оракул достаточно умен, чтобы преобразовать менее эффективный (в зависимости от того, что это) в другой. Поэтому я думаю, что ответ должен скорее зависеть от читаемости каждого (где я думаю, что IN
явно выигрывает)
Оператору OR требуется гораздо более сложный процесс оценки, чем конструктор IN, поскольку он допускает множество условий, а не только таких, как IN.
Вот что вы можете использовать с OR, но не совместимы с IN: больше. больше или равно, меньше, меньше или равно, LIKE и еще немного похоже на oracle REGEXP_LIKE. Кроме того, учтите, что условия могут не всегда сравнивать одно и то же значение.
Для оптимизатора запросов проще управлять оператором IN, потому что это только конструктор, который определяет оператор OR в нескольких условиях с оператором = с тем же значением. Если вы используете оператор OR, оптимизатор может не учитывать, что вы всегда используете оператор = 1 на одном и том же значении и, если он не выполняет более глубокую и очень сложную разработку, он, вероятно, может исключить, что может быть только = операторы для одних и тех же значений во всех задействованных условиях с последующим исключением оптимизированных методов поиска, таких как уже упомянутый двоичный поиск.
[EDIT] Вероятно, оптимизатор может не реализовать оптимизированный процесс оценки IN, но это не исключает, что однажды это может произойти (с обновлением версии базы данных). Поэтому, если вы используете оператор OR, оптимизированная разработка не будет использоваться в вашем случае.
OR
имеет смысл (с точки зрения удобочитаемости), когда меньше сравниваемых значений.
IN
полезен особенно. когда у вас есть динамический источник, с которым вы хотите сравнить значения.
Другой альтернативой является использование JOIN
с временной таблицей.
Я не думаю, что производительность должна быть проблемой, если у вас есть необходимые индексы.
Я сделал запрос SQL в большом количестве OR (350). Postgres делают это 437.80мс.
Теперь используйте IN:
23.18ms