我有一个Oracle查询的结构如下:
SELECT * FROM table WHERE X='true' OR Y IN (complicated subquery)
如果Oracle看到X确实等于“true”,那么它仍然会尝试评估WHERE子句的Y IN(子查询)部分?此外,在这样的语句中,子查询将对表中的每个条目执行多次?我会像以下这样的东西更好吗?
WITH subQ as (complicated subquery) SELECT * FROM table WHERE X='true' OR Y IN (SELECT id FROM subQ)
解决方法
这取决于.
.
通常,Oracle不保证sql语句将使用短路评估(尽管PL / sql保证执行短路评估). Oracle优化器可以按预期的最有效率的顺序自由地评估谓词.这可能意味着首先评估第一个谓词,只有匹配的行具有第二个谓词,但完全可能发生相反的情况,或者Oracle将查询转换为一种UNION,并在组合结果之前完全评估两个谓词.
.
通常,Oracle不保证sql语句将使用短路评估(尽管PL / sql保证执行短路评估). Oracle优化器可以按预期的最有效率的顺序自由地评估谓词.这可能意味着首先评估第一个谓词,只有匹配的行具有第二个谓词,但完全可能发生相反的情况,或者Oracle将查询转换为一种UNION,并在组合结果之前完全评估两个谓词.
就是说,如果优化器可以在编译时确定谓词总是会被计算为TRUE或FALSE,则优化器应该将其视为常量.因此,例如,如果表格上有一个约束,阻止X的值为“true”,则优化程序根本不应该评估第二个谓词(尽管不同版本的优化程序将具有不同的检测能力某些东西在编译时是一个常数).
至于你的问题的第二部分,没有看到查询计划,这是很难说的.如果有更有效的方法来评估,Oracle优化器往往将从一种形式的查询转换到另一种形式.然而,一般来说,如果subQ与表相比返回相对较大数量的行,则将查询结构作为EXISTS而不是IN来更有效.