IN和OR中的SQL WHERE子句
在处理大型数据库时,哪些性能更好, IN
或OR
中的SQL Where
?
他们被执行的方式有什么不同吗?
我假设你想知道下面的性能差异:
WHERE foo IN ('a', 'b', 'c') WHERE foo = 'a' OR foo = 'b' OR foo = 'c'
根据MySQL手册,如果值是恒定的,则对列表进行sorting,然后使用二进制search。 我会想象一下, 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%。 增加更多的术语会使差异更大。 其他数据库和其他数据的结果可能会有所不同。
最好的方法是查看执行计划。
我用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')
我认为甲骨文很聪明,可以将效率较低的一方(无论哪一方)转换成另一方。 所以我认为答案应该取决于每个可读性(我认为IN
明显胜出)
OR运算符需要比IN构造更复杂的评估过程,因为它允许许多条件,不仅等于IN。
这是一个你可以使用OR但是与IN不兼容的东西:更大。 大于或等于,小于,小于或等于,LIKE和一些更像oracle的REGEXP_LIKE。 另外考虑到条件可能不总是比较相同的价值。
对于查询优化器来说,更容易pipe理IN运算符,因为它只是一个在多个条件中使用=运算符在相同值上定义OR运算符的结构。 如果使用OR运算符,优化程序可能不会认为您始终使用相同值的=运算符,并且如果它没有执行更深入和更复杂的阐述,则可能排除可能只有=运算符在所有涉及的条件下具有相同的值,随后排除优化的search方法,如已经提到的二进制search。
[编辑]可能优化器可能不会实现优化的IN评估过程,但这并不排除它可能发生的一次(数据库版本升级)。 所以如果你使用优化精化的OR运算符将不会在你的情况下使用。
OR
是有意义的(从可读性的angular度来看),当有较less的值进行比较。 IN
尤其有用。 当你有一个dynamic的来源,你想要比较值。
另一种方法是使用JOIN
和临时表。
如果您有必要的索引,我不认为性能应该是一个问题。
我做了大量的OR(350)SQL查询。 Postgres做437.80ms 。
现在使用IN:
23.18ms