2016-06-15 112 views
43

当我们使用等号和IN运算符具有相同的值时,SQL引擎有什么不同?执行时间是否改变?等于(=)和IN之间的性能差异与一个值

一日一使用平等检查操作

WHERE column_value = 'All' 

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

WHERE column_value IN ('All') 

是否SQL引擎改变IN=如果只有一个值吗?

在MySQL和PostgreSQL中有相同的区别吗?

+19

不要试图学习数以百万计的规则,这在某种程度上意味着你总是会写出尽可能绝对性能最好的代码。写清楚,简单,*可以理解的*代码,显然会产生正确的结果。设定绩效目标。然后*测量*您的代码的性能。如果它充分执行,继续前进。只有在表现不佳的情况下,你才应该花更多时间。在那个时候,尝试像你的问题那样的微小变化,然后再次测量*就很简单。也许一个比另一个更快,但*它是否会产生显着差异*? –

+3

同意@Damien_The_Unbeliever。但是有时我在写单行或单词时更担心SQL –

+1

它们是99.9999999%相同。只要你不做类似'WHERE column_value IN((从list_of_values中选择值,其中value ='All'limit 1))''那么你很好。 ()语句中的子查询带来了巨大的影响。 – MonkeyZeus

回答

41

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

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

后大网上搜索,我发现了SQL文件来支持这个(我认为它适用于所有DBMS):

如果只有一个括号内的值,这称道的是相当于

WHERE “栏”=“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 | 
----------------------------------------------------- 

正如你可以看到,二者相。这是一个索引列。同样适用于无索引的列(只是全表扫描)。

+0

你对此有任何数据库的官方参考吗?我试过搜索,但没有得到。 –

+0

@SomnathMuluk更新了答案 – sagi

+0

@SomnathMuluk: - 我不认为有这样的MySQL官方参考。如果您发现结果之间存在任何差异,您可以创建一个测试用例并自行测试。 –

8

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

在Mysql和PostgresSQL中有相同的区别吗?

不,它不会对两台发动机有什么区别(逸岸它会为大多数数据库中包括SQL服务器,Oracle等相同)。两个引擎将转换为为=

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子句多个值,最好将它们转换成连接

+3

我已经提到过只有一个值。 –

+0

@SomnathMuluk:仅针对一个子句进行更新 – TheGameiswar

5

确实没有什么大的差别,但是如果column_value已编入索引,则IN运算符可能不会将其作为索引读取。

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

1

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

我相信他们将具有相同的执行计划,因为只有一个值放在IN()语句中时,它将以与正常=符号相同的方式执行。

没有理由让优化器在像这样的查询上表现任何不同。

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行告诉我们查询是通过比较一个常数值和这个索引来执行的。

2

只是为了添加不同的视角,rdbms系统的要点之一就是他们会为您重写您的查询,并为该查询和所​​有等价的查询选择最佳执行计划。这意味着只要两个查询在逻辑上相同,应始终在给定的rdbms上生成相同的执行计划。这就是说,许多查询是等价的(相同的结果集),但仅仅是因为数据库本身并不知道的约束,所以要小心这些情况(例如,对于数字为1-6的标志字段,数据库不会不知道<3in (1,2)相同)。但是在一天结束时,如果您只是在考虑andor声明的易读性,那么您写入它们的方式对性能没有影响。

相关问题