在处理大型数据库时,哪个性能更好,IN
还是OR
在SQL Where
子句中?
它们的执行方式有什么不同吗?
在处理大型数据库时,哪个性能更好,IN
还是OR
在SQL Where
子句中?
它们的执行方式有什么不同吗?
Answers:
我假设您想知道以下两者之间的性能差异:
WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'
根据MySQL手册,如果值是常数IN
,则对列表进行排序,然后使用二进制搜索。我可以想象一下,OR
它们没有特定的顺序进行逐一评估。因此IN
在某些情况下更快。
最好的了解方法是使用特定数据在数据库中同时对它们进行概要分析,以查看哪种方法更快。
我在具有1000000行的MySQL上都尝试过。对列进行索引后,性能没有明显的区别-两者几乎都是即时的。当该列未建立索引时,我得到了以下结果:
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%左右。添加更多术语会使差异更大。结果可能在其他数据库和其他数据上有所不同。
IN
方法的额外结构比一堆可能的相关OR
子句更易于优化。如果有一个OR
方法更快的引擎,我会感到惊讶,但是有时候OR会更慢,我并不感到惊讶。
OR
替换为IN
?
找出答案的最佳方法是查看执行计划。
我在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')
INLIST ITERATOR
操作,如果有可以使用的索引,它将选择该操作。不过,当我尝试过了,双方IN
并OR
用相同的执行计划结束。
OR运算符需要比IN构造复杂得多的评估过程,因为它允许许多条件,不仅像IN一样。
这类似于可以与OR一起使用但与IN不兼容的事物:更大。大于或等于,小于,小于或等于LIKE以及更多类似oracle REGEXP_LIKE的对象。此外,请考虑条件可能并不总是比较相同的值。
对于查询优化器,管理IN运算符更容易,因为它只是一个在多个条件下定义OR运算符且=值相同的构造。如果您使用OR运算符,则优化器可能不会认为您始终在相同的值上使用=运算符,并且,如果它没有执行更深,更复杂的阐述,则可能会排除仅存在=在所有涉及的条件下都使用相同值的运算符,因此排除了已提到的二进制搜索之类的优化搜索方法。
[编辑]优化器可能未实现优化的IN评估过程,但这并不排除可能会发生一次(数据库版本升级)。因此,如果使用OR运算符,则在您的情况下将不使用优化的详细说明。