等于(=)和IN与一个值之间的性能差异

时间:2016-06-15 07:09:40

标签: mysql sql postgresql equals-operator in-operator

当我们使用等号和IN运算符具有相同的值时,SQL引擎有何不同?执行时间是否会改变?

第一个使用等式检查操作符

WHERE column_value = 'All'

第二个使用OR运算符和单值

WHERE column_value IN ('All')

如果只有一个值,SQL引擎会将IN更改为=吗?

MySQL和PostgreSQL中是否存在相同的差异?

7 个答案:

答案 0 :(得分:53)

这两个语句之间没有区别,当IN只有一个元素时,优化器会将=转换为IN

虽然当你有这样的问题时,只需运行两个语句,运行执行计划并查看差异。在这里 - 你找不到任何。

在网上进行了大量搜索之后,我发现了一个关于SQL的文档来支持这一点(我假设它适用于所有DBMS):

  

如果括号内只有一个值,则此推荐等同于

     

WHERE" column_name" =' value1

Here is the link to the document

以下是Oracle中两个查询的执行计划(大多数DBMS将对此进行相同处理):

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  |
-----------------------------------------------------

如您所见,两者都是相同的。这是在索引列上。同样适用于未编制索引的列(只需全表扫描)。

答案 1 :(得分:8)

使用单个值时没有区别。如果要检查上述两个查询的表扫描,索引扫描或索引搜索,您会发现两个查询之间没有区别。

  

Mysql和PostgresSQL中是否存在相同的差异?

不,它在两个引擎上没有任何区别(实际上,对于大多数数据库,包括SQL Server,Oracle等,它都是相同的)。两个引擎都会将IN转换为=

答案 2 :(得分:5)

确实没有太大差异,但如果 column_value 被编入索引,IN运算符可能无法将其作为索引读取。

遇到这个问题一次,所以要小心。

答案 3 :(得分:5)

教导一个人钓鱼等等。以下是如何亲自了解您的查询会有哪些变体:

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

您可以阅读here有关如何解释mysql EXPLAIN请求的结果的信息。现在,请注意我们为两个查询获得了相同的输出:生成完全相同的“执行计划”。 type行告诉我们查询使用非唯一索引(在这种情况下是外键),ref行告诉我们通过比较常量值来执行查询索引。

答案 4 :(得分:4)

对于单个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子句中有多个值,最好将它们转换为连接

答案 5 :(得分:2)

只是为了添加不同的视角,rdbms系统的一个要点是它们将为您重写查询,并为该查询和所​​有等效查询选择最佳执行计划。这意味着只要两个查询在逻辑上相同,就应该始终在给定的rdbms上生成相同的执行计划。

话虽如此,许多查询是等价的(相同的结果集),但仅仅是因为数据库本身不知道的约束,所以要小心这些情况(例如,对于数字为1-6的标志字段,db不会&# 39;知道<3in (1,2)相同。但是在一天结束的时候,如果你只考虑andor语句的易读性,那么就不会对你的写作方式产生影响。

答案 6 :(得分:1)

您需要在两者上运行执行计划,并查看结果。

我相信他们将拥有相同的执行计划,因为当=语句中只放置一个值时,执行计划与普通IN()符号相同。

优化器没有理由对这样的查询采取任何不同的行为。