Различия в производительности между равными (=) и IN с одним значением
Как отличаются SQL-механизмы, когда мы используем знак равенства, а оператор IN имеет одинаковое значение? Изменяется ли время выполнения?
1-й, используя оператор проверки равенства
WHERE column_value = 'All'
2nd, используя оператор OR и одно значение
WHERE column_value IN ('All')
Изменяет ли SQL-механизм IN
на =
только одно значение?
Есть ли разница в том же в MySQL и PostgreSQL?
Ответы
Ответ 1
Нет никакой разницы между этими двумя утверждениями, и оптимизатор преобразует IN
в =
, когда IN
имеет только один элемент в нем.
Хотя, когда у вас есть такой вопрос, просто запустите оба оператора, запустите их план выполнения и увидите различия. Здесь вы не найдете.
После большого поиска в Интернете я нашел документ на SQL для поддержки этого (я предполагаю, что он применим ко всем СУБД):
Если в круглой скобке есть только одно значение, это commend эквивалентно
WHERE "column_name" = 'value1
Вот ссылка на документ.
Вот план выполнения обоих запросов в Oracle (большинство СУБД будет обрабатывать это же):
EXPLAIN PLAN FOR
select * from dim_employees t
where t.identity_number = '123456789'
Plan hash value: 2312174735
-----------------------------------------------------
| Id | Operation | Name |
-----------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES |
| 2 | INDEX UNIQUE SCAN | SYS_C0029838 |
-----------------------------------------------------
И для IN()
:
EXPLAIN PLAN FOR
select * from dim_employees t
where t.identity_number in('123456789');
Plan hash value: 2312174735
-----------------------------------------------------
| Id | Operation | Name |
-----------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| DIM_EMPLOYEES |
| 2 | INDEX UNIQUE SCAN | SYS_C0029838 |
-----------------------------------------------------
Как вы можете видеть, оба они одинаковы. Это находится в индексированном столбце. То же самое касается неиндексированного столбца (просто полное сканирование таблицы).
Ответ 2
Нет никакой разницы, если вы используете его с одним значением. Если вы проверите сканирование таблицы, сканирование индекса или поиск индекса для вышеуказанных двух запросов, вы обнаружите, что между этими двумя запросами нет разницы.
Есть ли разница в том же в Mysql и PostgresSQL?
Нет, это не имело бы никакого значения для двух движков (Infact он был бы таким же для большинства баз данных, включая SQL Server, Oracle и т.д.). Оба двигателя преобразуют IN
в =
Ответ 3
На самом деле нет больших различий, но если ваш column_value индексирован, оператор IN
не может читать его как индекс.
Однажды встретила эту проблему, поэтому будьте осторожны.
Ответ 4
Научите человека ловить рыбу и т.д. Здесь, как увидеть сами, какие варианты ваших запросов будут делать:
mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id = "AMH"\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: sentence
type: ref
possible_keys: sentence_lang_id
key: sentence_lang_id
key_len: 153
ref: const
rows: 442
Extra: Using where
И попробуем другое:
mysql> EXPLAIN SELECT * FROM sentence WHERE sentence_lang_id in ("AMH")\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: sentence
type: ref
possible_keys: sentence_lang_id
key: sentence_lang_id
key_len: 153
ref: const
rows: 442
Extra: Using where
Вы можете прочитать здесь о том, как интерпретировать результаты запроса mysql EXPLAIN
. Напомним, что мы получили идентичный вывод для обоих запросов: создается тот же самый "план выполнения". Строка type
сообщает нам, что запрос использует неидеальный индекс (в этом случае внешний ключ), а строка ref
сообщает нам, что запрос выполняется путем сравнения значения константы с этим индексом.
Ответ 5
Для отдельного пункта IN нет никакой разницы. Ниже приведена демонстрация использования таблицы EMPS, которая у меня есть.
select * from emps where empid in (1)
select * from emps where empid=1
Предикат для первого запроса в плане выполнения:
[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0)
Предикат для второго запроса в плане выполнения:
[PerformanceV3].[dbo].[Emps].[empID]=CONVERT_IMPLICIT(int,[@1],0)
Если у вас есть несколько значений в IN Clause, лучше их преобразовать в объединение
Ответ 6
Чтобы добавить другую перспективу, одним из основных моментов систем rdbms является то, что они перепишут ваш запрос для вас и выберут лучший план выполнения для этого запроса и всех эквивалентных. Это означает, что до тех пор, пока два запроса логически идентичны, он должен всегда генерировать один и тот же план выполнения для данного rdbms.
При этом многие запросы эквивалентны (один и тот же набор результатов), но только из-за ограничений, которые сама база данных не знает, поэтому будьте осторожны в этих случаях (например, для поля флага с цифрами 1-6, db doesn ' t know <3
совпадает с in (1,2)
). Но в конце дня, если вы просто думаете о удобочитаемости операторов and
и or
, это не повлияет на производительность, как вы их пишете.
Ответ 7
Вам нужно будет запустить план выполнения для обоих и посмотреть результаты.
Я считаю, что они будут иметь один и тот же план выполнения, поскольку он будет выполняться так же, как обычный знак =
, когда внутри оператора IN()
помещается только одно значение.
Нет никаких причин, по которым оптимизатор будет вести себя иначе по запросу, подобному этому.