SQL-内部查询而非内部查询比完整查询花费的时间长?

SQL-内部查询而非内部查询比完整查询花费的时间长?,sql,oracle,Sql,Oracle,我在SQL查询中使用NOT 例如: select columnA from table1 where columnA not in ( select columnB from table2) 查询的这一部分怎么可能 select columnB from table2 需要30秒才能完成,但上面的整个查询需要0.1秒才能完成?? 完整的查询不应该花费30秒以上吗 顺便说一句,两个查询都返回有效结果 谢谢 评论回复 是因为第二个查询没有 实际完成但仅 返回第一个“x”行(输出 一张非常大的桌

我在SQL查询中使用NOT

例如:

select columnA 
from table1
where columnA not in (
select columnB
from table2)
查询的这一部分怎么可能

select columnB
from table2
需要30秒才能完成,但上面的整个查询需要0.1秒才能完成?? 完整的查询不应该花费30秒以上吗

顺便说一句,两个查询都返回有效结果

谢谢

评论回复


是因为第二个查询没有 实际完成但仅 返回第一个“x”行(输出 一张非常大的桌子?)

不,查询在30秒后完成,返回的行不多(例如50行)


但是@Aleksandar想知道为什么 关于表演的问题 杀手太快了

我的观点完全正确

还有,选择distinct需要多长时间 表2中的B列需要执行什么


实际上,最初的查询是“选择不同的…”

不是性能杀手

在某些SQL引擎上,首先在(…)中对临时表中的数据执行NOT操作,然后重新运行查询


如果可以,您应该只在!

中使用,因为它可以使用索引并且返回的结果数量很小。可能是这样。返回结果可能会导致执行时间。

这是因为查询优化程序将查询转换为看起来完全不同的内容。实际查询应该与查询生成的内容相同我喜欢这样:

select columnA 
from table1
left join table2 on ColumnA = ColumnB
where ColumnB is null

如果数据库可以使用索引连接表,那么它可能不必查询整个表2,甚至不必触摸表本身。

一个戏剧性的比较,让我们这样说吧

select columnB
from table2
…有十亿行(30秒),许多数据通过导线传输并呈现给用户

而这个

select columnA 
from table1
…只有一行

如果您不打算显示table2的数据,RDBMS不会将table2的数据从服务器拉到客户机。因此,在进行数据存在性测试时,不会涉及太多的网络带宽或I/O,这一切都发生在服务器上,唯一可以从服务器拉到客户机的是table1的一行

select columnA 
from table1
where columnA not in (
select columnB
from table2)
如果你的columnA和columnB碰巧有索引,事情会特别快


使数据库操作变慢的因素有两个:第一个是当您从服务器向客户端拉取太多数据时,第二个是当您在相关字段上没有索引时,请确保您知道它们之间的区别

如果“columnA”为NULL,则不会通过您正在查看的NOT-IN解决方案返回它,但是已经提供的左侧反连接示例将表现为NOT-EXISTS

另外,确保TOAD/SQL Developer不会像他们喜欢的那样“只显示前50名”(从表1中选择计数(*),看看50是否确实是查询结果)


对查询执行一个解释计划,看看它是否突出显示了任何看起来异常的内容——检查索引,并查看列是否允许空值——缺少索引可能是罪魁祸首,但从空值进行全表扫描可能会导致噩梦)。

您似乎认为主查询包含以下步骤:

(1)  Run the subquery
(2)  Check each row in table1 against the result set from the subquery.
因此,您认为单独运行子查询所花费的时间必须少于运行整个查询所花费的时间

但是SQL不是一种过程语言,查询的结构不一定意味着执行查询所遵循的步骤

正如Guffa所回答的,优化器将提出(它认为是)一个执行每个查询的最佳计划。这些执行计划在查看查询时并不总是显而易见的,在某些情况下确实可能非常违反直觉

我认为,在这种情况下,与一次查询所有表2中的值相比,优化器很可能想出了一种更快的方法来检查表2中是否存在值。这可能是Guffa所展示的转换(尽管这仍然不能告诉您所使用的确切执行计划)

我猜table1的行数明显少于table2,并且table2.columnB上存在一个索引。因此,它所要做的就是从table1中获取行,然后探测每个值的索引以检查是否存在。但这只是一种可能性


此外,正如Michael Buen指出的,返回的结果集大小的差异也会影响您的感知性能。我的直觉是,这是执行计划差异的次要原因,但可能很重要。

是因为第二个查询实际上尚未完成,但只返回了第一个“x”行吗(从一张很大的桌子上拿出来?)表2是否非常大,因为一个列上的正常选择需要30秒才能完成?您能看一下这两个表的执行计划吗?或者更好:将两个计划与两个表的DDL一起发布。@Aleksandar Tomic,您的问题的答案在于您拒绝给我们的细节。您需要意识到SQL本质上是声明性的。您指定“什么"你需要,让数据库拿出一个算法来解决它。现在,数据库正在做一些有趣的事情,因为下面的细节。如果你向我们展示精确的查询、解释计划以及所有引用表的创建脚本,这些细节就会被揭示出来。但是@Aleksandar想知道为什么会出现这个问题性能杀手太快了。NOT IN可能非常高效。如果运算符两侧的列都定义为NOT NULL,NOT IN将打开非常高效的访问路径(哈希反连接、嵌套循环反连接…)。OP的查询中可能会发生这种情况。想想看:如果某个功能总是不好,它就会被删除。可以。是的,使用索引会更好,但不是每次都(想想太多)说“不是性能杀手”是(a)过度概括,和(b)与所问的实际问题无关。Ok,Ok NOT有时是性能杀手……关于acces的评论不是这样吗