SQL-IN与非IN

SQL-IN与非IN,sql,Sql,假设我有一个表,其中列的值从1到10。我需要选择除9和10之外所有值的列。使用此查询时是否会有差异(性能方面): SELECT * FROM tbl WHERE col NOT IN (9, 10) 这个呢 SELECT * FROM tbl WHERE col IN (1, 2, 3, 4, 5, 6, 7, 8) 当谈到性能时,您应该始终分析您的代码(即,运行查询几千次,并使用某种秒表测量每个循环的性能) 但在这里,我强烈建议使用第一个查询,以便更好地维护未来的应用程序。逻辑是,除了9和

假设我有一个表,其中列的值从1到10。我需要选择除9和10之外所有值的列。使用此查询时是否会有差异(性能方面):

SELECT * FROM tbl WHERE col NOT IN (9, 10)
这个呢

SELECT * FROM tbl WHERE col IN (1, 2, 3, 4, 5, 6, 7, 8)

当谈到性能时,您应该始终分析您的代码(即,运行查询几千次,并使用某种
秒表测量每个循环的性能)

但在这里,我强烈建议使用第一个查询,以便更好地维护未来的应用程序。逻辑是,除了9和10之外,您需要所有记录。若将值11添加到表中并使用第二个查询,应用程序的逻辑将被破坏,这当然会导致bug


编辑:我记得这被标记为php,这就是我用php提供示例的原因,但我可能弄错了。我想用您正在使用的语言重写该示例并不困难。

对于常量列表,MySQL将在内部将您的代码扩展为:

SELECT * FROM tbl WHERE ((col <> 9 and col <> 10))
从tbl中选择*,其中((第9列和第10列))
另一个相同,改为8次
=


因此,是的,第一个会更快,需要做的比较更少。但是,它是可测量的可能性是可以忽略的,与解析SQL和检索数据的一般开销相比,少量常量比较的开销是微不足道的。

我看到Oracle在优化某些查询时遇到了问题,其中NOT IN if列可为空。如果您可以用任何一种方式编写查询,那么就我而言,IN是首选

使用“IN”,因为它很可能会使DBMS在相应的列上使用索引

“NOT IN”理论上也可以转化为索引用法,但以一种更复杂的方式,DBMS可能不会“花费开销时间”使用。

“IN”语句的内部工作方式类似于一系列“OR”语句

例如:

SELECT * FROM tbl WHERE col IN (1, 2, 3)
SELECT * FROM tbl WHERE col NOT IN (9, 10)
等于

SELECT * FROM tbl WHERE col = 1 OR col = 2 OR col = 3
SELECT * FROM tbl WHERE col <> 9 AND col <> 10
“或”语句可能会导致一些性能问题,如本文所述:

当您执行NOT IN语句时,结果都是一样的,但结果具有逻辑拒绝。但是,您可以在性能上更好地编写和等效查询。在您的示例中:

SELECT * FROM tbl WHERE col IN (1, 2, 3)
SELECT * FROM tbl WHERE col NOT IN (9, 10)
等于

SELECT * FROM tbl WHERE col = 1 OR col = 2 OR col = 3
SELECT * FROM tbl WHERE col <> 9 AND col <> 10
从第9列和第10列的tbl中选择*

使用“AND”语句,当所有条件之一为false时,数据库将停止分析,因此,它的性能比“in”语句中的“OR”或“used in”要好得多。

介于1和8之间可能更可取,但即使考虑到如此小的表的问题,也不值得花费任何时间。你的实际情况不同吗?对不起,你说得对。删除。@Martin Smith-我将其视为一种理论情况,我不打算使用这些查询:)性能也将因使用的DBMS而有很大差异。总是先检查执行计划,然后你就会看到。会有性能差异吗?很有可能,但是哪个更快取决于您使用的sql server、它的优化器有多好、您的索引以及它的行统计数据最近有多快、有多准确,以及col值的分布。OP没有告诉我们它们在什么RDBMS上,但在MySQL中,一个带有常量列表的
中的AFAIK是通过对列表的二进制搜索而不是8
=
比较来实现的。即使是这样(我从不指望MySQL做任何“高级”优化,这是最安全的假设)从理论上讲,这会使第二个稍微慢一点,因为还有更多的比较要做。查询的
版本中的
只占
而不是
版本的成本的1%。另外,
NOT IN
查询抱怨缺少索引。您可能认为优化器足够聪明,能够识别等价性,但显然不是
中获胜!