我们给出 where 条件的顺序会影响性能吗? [复制]

Posted

技术标签:

【中文标题】我们给出 where 条件的顺序会影响性能吗? [复制]【英文标题】:Does the order in which we are giving the where conditions affect performance? [duplicate] 【发布时间】:2015-07-15 13:26:31 【问题描述】:

我最近开始学习 oracle。我听说如果我们不遵循where 条件的顺序特别是当我们加入两个或多个表时,将会出现一些性能问题(如果我错了请纠正我)在 SQL 查询中。如果是这种情况,应该遵循什么样的顺序,我应该考虑哪些因素。请在 general 中进行解释,对于以下场景,假设我有 3 张桌子。 请找到 DDL 和 Sample data here 。

Part_material有基本信息,ID为Primary Key(PK), 表Component 将有不同类型的组件,其 ID,part_name 为 PK,每个 ID 将有 30 到 40 个条目, 表connection 将包含连接信息。我正在加入这三个表,如下所示:

select com.id,part.part_material,com.part_name,'TRUE',part.map_id,part.quantity,'INBOUND'
                            from    Components com,Base_part part,connects rel
                            where   part.id=com.id 
                            and     dbms_lob.compare(com.part_value,'Coat wi........')=0
                            and     part.part_material in ('Barium','Tungston','Carbon')  
                            and     com.part_name='Build Material'
                            and     rel.fromid=part.id
                            and     rel.fromid=com.id
                            and     rel.relname in ('Export Need','Not Molten');

如果我改变上述顺序,它会提高/降低性能吗?

【问题讨论】:

当优化器分析查询时,它会重新排序您的查询,如果它认为它会使您的查询更快,甚至可能重写它。所以不,我不希望您通过移动条件来看到性能上的任何差异(除非您通过这样做更改查询的语义含义)。但是你可以通过移动东西并比较解释计划来自己检查这一点。只需使用使其可读的顺序,以及为什么不使用 ANSI 连接。 :) 很有趣的问题。我只是猜测 mysql 做了类似于short circuit evaluation 的事情,但后来我发现了this question。我猜想 WHERE 顺序会很重要(比较主键会更快),但是由于 SQL 的不同实现会在不同方向上迭代 where 子句,所以很难说更改顺序是否会影响性能。 @sstan:谢谢。好的,我会检查解释计划。是的,我将开始使用 ANSI 连接 :) @DaveChen。谢谢你的链接 :)。那对我来说是新的。我从来不知道短路评估。 【参考方案1】:

Oracle 基于成本的优化器通常不受 WHERE 子句顺序的影响。

Tom Kyte 在 2009 年也回答了:

https://asktom.oracle.com/pls/asktom/f?p=100:11:0%3A%3A%3A%3AP11_QUESTION_ID:1857060700346051220

【讨论】:

如果汤姆·凯特这么说,那我相信。 :) 嗯,他并不经常犯错,但是,即使他说过类似“如果我不证明它,就挑战它”的话。 ;) 无论 Tom 说什么,我们都不能 100% 确定基于规则的东西隐藏在 Oracle 深处的某个地方。【参考方案2】:

执行策略由优化器决定,与where子句中的条件顺序或from子句中的表顺序无关。 您使用的语法非常古老且容易出错:开始使用 JOIN 语法来编写表之间的条件。

select com.id,part.part_material,com.part_name,'TRUE',part.map_id,part.quantity,'INBOUND'
                        from    Components com
                        join    Base_part part on part.id=com.id
                        join    connects rel on  rel.fromid=part.id
                                             and rel.fromid=com.id
                        where   dbms_lob.compare(com.part_value,'Coat wi........')=0
                        and     part.part_material in ('Barium','Tungston','Carbon')  
                        and     com.part_name='Build Material'
                        and     rel.relname in ('Export Need','Not Molten');

这样更防错更清晰

【讨论】:

"有时可以提高性能,因为优化器可以选择更好的执行路径"——这不是真的(至少对于 Oracle 而言)。连接条件的顺序和连接的类型(where 子句中的隐式连接与显式 JOIN)不会影响性能。事实上,Oracle 内部对这两种连接类型的处理方式完全相同。但我同意使用明确的JOIN 是更好的编码风格。 完全同意 a_horse_with_no_name。我喜欢你的帖子,但最后一部分不是真的。考虑对其进行编辑,或查找并包含支持您声明的信息。 "您使用的语法非常陈旧且容易出错"...嗯,实际上,Oracle 优化器可以并且确实将 ANSI 语法重写为旧式加入幕后。查看select * from dual d1 left outer join dual d2 on (d1.dummy = d2.dummy); 的解释计划 - 在谓词部分下,我看到了3 - filter("D1"."DUMMY"="D2"."DUMMY"(+))。那是在 11.2.0.2;我不确定在 v12 中是否仍然如此。实际上更可能是 ANSI 样式更容易出错(事实上,它在首次引入时存在很多错误!) (虽然不要认为我反对 ANSI 语法连接;这需要一段时间,但我正在热身!*:-)) @Boneist:“容易出错”,我认为他的意思是作为编写 SQL 的人,我可以更轻松地使用旧的连接语法与 ansi 连接语法编写不正确的查询。对于左连接尤其如此。只需在一个条件下忘记一点(+),您的查询就会被破坏。我曾经是一个铁杆的老加入语法人。但我会第一个承认,自从我切换到 ansi 连接语法后,我的查询的错误更少。【参考方案3】:

如果您使用基于规则的优化器(或 +rule 提示),where 子句的顺序非常重要。但强烈建议使用基于成本的优化器。 请注意:只要 Oracle 支持基于规则的优化器,您就无法 100% 确定基于规则的内容隐藏在代码中的某个位置……无论 Tom Kyte(SQL 专家)怎么说。

【讨论】:

为什么要投反对票?在德国甲骨文会议 (DOAG) 上,一位演讲者告诉我们,如果一切都失败了,他有时会使用 +rule 提示!这是中欧最著名和最著名的甲骨文咨询公司的人。顺便说一句,这种观点独立于 Oracle!

以上是关于我们给出 where 条件的顺序会影响性能吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

SQL where 条件顺序对性能的影响有哪些

SQL 问题:WHERE 子句的顺序有区别吗?

where条件顺序与建索引顺序

性能优化实战-join与where条件执行顺序

Postgres 表中列的顺序会影响性能吗?

列数会影响查询性能吗?