我最近在接受采访时问了这个问题:
假设我有一个像
这样的SQL查询select A.a
from A JOIN B on A.b=B.c
现在正常和有效方式在这种情况下首先根据连接条件过滤掉A和B中的记录,然后进行连接。
面试官要我给出一个场景(不仅仅是上面给出的选择,还有其他任何内容)哪里有效的方式是首先进行加入,然后选择
当时我想不出任何这样的操作员或场景,也无法回答它,即使现在我也无法想到它。任何人都可以告诉我任何这样的场景吗?
更新:上述查询只是解释正常执行过程的一个示例。答案不是,肯定不会只是一个选择操作,但将包括一些其他操作,如联盟,交叉点等。面试官想知道其他条件
答案 0 :(得分:2)
当过滤费用高于加入谓词的费用时,在join
之前评估where
条件可能更有效:
create table Users (id int, name nvarchar(255));
create table Comments (userid int, commentText nvarchar(max));
create index IX_Comments_Users on Comments (userid);
select c.*
from Comments c
inner join Users u on c.userid = u.id
where u.name = 'foobar' and c.commentText like '%f%'
虽然我只是猜测(并且很糟糕,但是),查询计划有望从Users
获得结果,并在Comments
上执行索引查找,查找,然后执行{ {1}}在最后。
但是,在现代数据库平台上,您不必考虑它:优化器将使用统计信息来估计行数,并且通常选择最有效的查询计划。我必须首先明确调整查询以评估like
子句的唯一时间是处理优化器没有架构信息的链接服务器。
where
然而,我再次强调,您在查询中编写的内容与查询的执行方式无关。 SQL Server和朋友可以在他们可以做的优化中获得惊人的辉煌。例如,如果存在具有相同标准的索引视图,则您的条件甚至可能无法在执行时进行评估 - 对于过滤的索引也可以这样说。
学习阅读查询计划,热爱查询计划,并通过“当生成的查询计划不是最佳,并且性能导致问题”来回答这些问题。使用SQL的任何其他方法都是神秘的思考。
答案 1 :(得分:0)
这些评论基于Oracle和SQL Server。将特定数据库作为标记放入是有帮助的,因为这类问题的答案可能是数据库特定的。
查询计划程序决定是否在连接之前或之后过滤记录,除非您使用子表和类似的东西来混淆它。
我能想到基于成本的优化器希望在连接之后过滤的唯一原因是它需要外连接的输出来评估某些内容,或者谓词需要一个calc来自两个表格
在您的示例查询中,它将对两个表执行某种扫描,然后进行某种类型的连接。
基于连接谓词,它不能/不会在连接之前“预先过滤”记录,因为它必须事先做某种哈希/连接以识别记录,这是工作的两倍,基于成本的优化工作者不会选择两倍的工作。
如果查看查询计划...它总是在SELECT之前进行连接,因为SELECT是计划中的最后一个。所以你可能希望澄清你的第二个陈述。
我认为你的面试官必须暗指其他事情,但我不确定是什么。
事实上,优化器总是尝试减少进入连接运算符的记录(通过过滤),因此连接运算符的工作量较少。