在处理SQL IN
- 子句中表现更好,OR
或Where
的大型数据库时?
执行方式有什么不同吗?
答案 0 :(得分:150)
我假设您想知道以下内容之间的性能差异:
WHERE foo IN ('a', 'b', 'c')
WHERE foo = 'a' OR foo = 'b' OR foo = 'c'
根据manual for 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%。添加更多术语会使差异更大。结果可能因其他数据库和其他数据而异。
答案 1 :(得分:31)
最好的方法是查看执行计划。
我尝试使用 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')
答案 2 :(得分:6)
我认为oracle非常聪明,可以将效率较低的(无论哪种)转换为另一种。所以我认为答案应该取决于每个人的可读性(我认为IN
明显胜出)
答案 3 :(得分:6)
OR运算符需要比IN结构更复杂的评估过程,因为它允许许多条件,而不仅仅是像IN一样。
以下是与OR一起使用但与IN不兼容的内容: 更大。更大或更小,更少,更少或相等,LIKE和更多像oracle REGEXP_LIKE。 另外考虑条件可能并不总是比较相同的值。
对于查询优化器,它更容易管理IN运算符,因为它只是一个构造,它在多个条件下定义OR运算符,并且=运算符在相同的值上。如果你使用OR运算符,优化器可能不会认为你总是在相同的值上使用=运算符,如果它没有执行更深入和更复杂的细化,它可能会排除可能只有=运算符在所有相关条件下的相同值,随后排除优化的搜索方法,如已经提到的二进制搜索。
[编辑] 可能优化器可能没有实现优化的IN评估过程,但这并不排除一次可能发生(使用数据库版本升级)。因此,如果使用OR运算符,则不会在您的情况下使用优化精化。
答案 4 :(得分:1)
OR
有意义(从可读性的角度来看),当要比较的值较少时。
IN
非常有用。如果您有动态源,您希望与之比较值。
另一种方法是将JOIN
与临时表一起使用
如果您有必要的索引,我认为性能不应该是一个问题。
答案 5 :(得分:1)
我在大量的OR(350)中进行了SQL查询。 Postgres做到 437.80ms 。
现在使用IN:
<强> 23.18ms 强>