我在SQL查询中使用NOT IN。
例如:
select columnA
from table1
where columnA not in (
select columnB
from table2)
查询的这一部分怎么可能
select columnB
from table2
需要30秒才能完成,但上面的整个查询需要0.1秒才能完成? 整个查询不应该需要30秒+?
BTW,两个查询都返回有效结果。
谢谢!
评论回答
是因为第二个查询没有 实际完成但只有 返回第一个'x'行(out 一张非常大的桌子?)
不,查询在30秒后完成,而不是返回多行(例如50)。
但@Aleksandar想知道为什么 质疑表现的问题 杀手是如此之快。
我的观点正是
选择不同多长时间 table2中的columnB执行?
实际上,原始查询是“select distinct ...
答案 0 :(得分:4)
这是因为查询优化器将查询转换为看起来完全不同的内容。实际查询应该与查询产生的查询相同:
select columnA
from table1
left join table2 on ColumnA = ColumnB
where ColumnB is null
如果数据库可以使用索引来连接表,也许它不必查询整个table2,甚至不需要触摸表本身。
答案 1 :(得分:4)
您似乎认为主要查询意味着以下步骤:
(1) Run the subquery
(2) Check each row in table1 against the result set from the subquery.
因此,您认为分别运行子查询必须花费的时间少于运行整个查询。
但SQL不是一种过程语言,查询的结构并不一定意味着执行查询将遵循的步骤。
当Guffa回答时,优化器会提出(它认为是)执行每个查询的最佳计划。通过查看查询,这些执行计划并不总是显而易见的,在某些情况下确实可能非常违反直觉。
我认为在这种情况下,最有可能的是,优化器提出了一种更快的方法来检查table2中是否存在值,而不是简单地一次查询所有table2。这可能是Guffa所展示的转变(虽然这仍然没有告诉你使用的确切执行计划)。
我猜测table1的行数比table2少得多,而且table2.columnB上存在一个索引。所以它要做的就是从table1中获取行,然后探测每个值的索引以检查是否存在。但这只是一种可能性。
此外,正如Michael Buen指出的那样,返回的结果集大小的差异也会影响您的感知表现。我的直觉是,这是执行计划差异的次要因素,但它可能很重要。
答案 2 :(得分: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碰巧有一个索引
,事情会特别快使数据库操作变慢的因素有两个:第一个是从服务器向客户端提取过多数据,第二个是在相关字段上没有索引时
答案 3 :(得分:0)
当它可以使用索引时,返回的结果数量很少。有可能。返回结果可能会导致执行时间。
答案 4 :(得分:0)
进入,请确保您了解NOT In and NOT EXISTS之间的区别。
如果“columnA”为NULL,则不会通过您正在查看的NOT IN解决方案返回,但已经提供的LEFT反连接示例将表现为NOT EXISTS。
另外,确保TOAD / SQL Developer不只是“显示他们喜欢做的前50名”(从table1执行select count(*)以查看50是否确实是查询结果。)
对查询执行EXPLAIN PLAN并查看它是否突出显示任何看起来很恶劣的内容 - 检查索引并查看列是否允许NULLS - 缺少索引可能是罪魁祸首但是来自NULLS的全表扫描可能是造成噩梦)。
答案 5 :(得分:-1)
不是性能杀手。
在某些SQL引擎上首先将in(...)转换为临时表,重新运行查询,对临时表中的数据执行NOT。
如果可以,您应该只使用IN!