Различия в производительности между equal ( = ) и IN с одним значением

чем отличаются SQL-движки, когда мы используем знак равенства и оператор IN имеет одинаковое значение? Меняется ли время выполнения?

1-й с помощью оператора проверки равенства

WHERE column_value = 'All'

2-й с помощью оператора OR и одного значения

WHERE column_value IN ('All')

изменяется ли SQL engine IN to = Если есть только одно значение?

есть ли разница для того же в MySQL и PostgreSQL?

7 ответов


нет никакой разницы между этими двумя утверждениями, и оптимизатор преобразует IN до =, когда IN есть только один элемент в нем.

хотя, когда у вас есть такой вопрос, просто запустите оба оператора, запустите их план выполнения и посмотрите различия. Здесь вы ничего не найдете.

после большого поиска в Интернете я нашел документ на SQL для поддержки этого (я предполагаю, что это относится ко всем СУБД):

если есть только одно значение внутри скобки, эта рекомендация эквивалентна

где "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  |
-----------------------------------------------------

как вы можете видеть, обе идентичны. Это в индексированном столбце. То же самое касается неиндексированного столбца (только полная таблица сканирование. )


нет никакой разницы, когда вы используете его с одно значение. Если вы проверите таблицу scan, index scan или index seek для вышеупомянутых двух запросов, вы обнаружите, что нет никакой разницы между двумя запросами.

есть ли разница для того же в Mysql и PostgresSQL?

нет, это не будет иметь никакого значения на двух двигателях(Infact это будет то же самое для большинства баз данных, включая SQL Server, Oracle и т. д.). Оба двигателя преобразуют IN до =


на самом деле нет больших различий, но если ваш column_value индексируется, IN оператор не может читать его как индекс.

столкнулся с этой проблемой один раз, поэтому будьте осторожны.


научите человека рыбачить и т. д. Вот как увидеть для себя, какие варианты ваших запросов будут делать:

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 запрос. На данный момент обратите внимание, что мы получили идентичный вывод для обоих запросов: генерируется точно такой же "план выполнения". The type строка сообщает нам, что запрос использует не уникальный индекс (внешний ключ, в этом случае), и ref строка сообщает нам, что запрос выполняется путем сравнения постоянного значения с этим индексом.


для предложения single IN нет никакой разницы..ниже демо через пуп стола у меня нет..

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, лучше преобразовать их в joins


чтобы добавить другую перспективу, один из основных моментов систем СУБД заключается в том, что они перепишут ваш запрос для вас и выберут лучший план выполнения для этого запроса и всех эквивалентных. Это означает, что до тех пор, пока два запроса логически идентичны, всегда должен генерировать один и тот же план выполнения для данной СУБД.

при этом многие запросы эквивалентны (тот же результирующий набор), но только из-за ограничений, о которых сама база данных не знает, поэтому осторожно с этими случаями (например, для поля флага с номерами 1-6, db не знает <3 Это то же самое, что in (1,2)). Но в конце концов, если вы просто думаете о разборчивости and и or заявления это не будет иметь значения для производительности, каким образом вы их пишете.


вам нужно будет запустить план выполнения на обоих, и посмотреть результаты.

Я считаю, что у них будет такой же план выполнения, как и у обычного = знак, когда внутри IN() заявление.

нет причин для оптимизатора вести себя по-разному в таком запросе.