【发布时间】:2018-07-25 06:31:08
【问题描述】:
UNION 和UNION ALL 查询在某些情况下可以胜过使用OR 连接谓词的等效查询。据我所知,这部分是因为UNION 子选择可以并行执行,因此它们可以有自己的“子计划”特定于OR-connected 谓词的每个部分,这可能是最优的,因为更简单的适用查询转换。
但是编写OR-connected 谓词通常更具可读性和简洁性,即使将子查询分解应用于UNION ALL 解决方案也是如此。我的问题是:有没有办法向 Oracle 表明,一个单一的、昂贵的 OR-connected 谓词应该转换为 UNION ALL 操作?如果有这样的提示/方法,在什么情况下可以应用(例如,谓词所涉及的列上是否需要存在任何约束等)?一个例子:
CREATE TABLE a AS
SELECT 1 x, 2 y FROM DUAL UNION ALL
SELECT 2 x, 1 y FROM DUAL;
-- This query...
SELECT * FROM a
WHERE x = 1 OR y = 1
-- Is sometimes outperformed by this one, for more complex table sources...
-- Note: in my case, I can safely apply UNION ALL. I know the two predicates to
-- be mutually exclusive.
SELECT * FROM a
WHERE x = 1
UNION ALL
SELECT * FROM a
WHERE y = 1
注意,我知道/*+ USE_CONCAT */ 提示:
SELECT /*+ USE_CONCAT */ * FROM a
WHERE x = 1 OR y = 1
但它似乎没有产生我需要的东西(执行计划中没有强制UNION ALL操作):
-------------------------------------------
| Id | Operation | Name | E-Rows |
-------------------------------------------
| 0 | SELECT STATEMENT | | |
|* 1 | TABLE ACCESS FULL| A | 2 |
-------------------------------------------
也许,这个提示有一些限制?我有 Oracle 11g2 可用于此。
【问题讨论】:
-
条件
x = 1 or y = 1将返回多少行(占所有行的百分比)(在真实表中)?在“或”查询中使用PARALLEL提示怎么样? -
@a_horse_with_no_name:实际上,(真实的)条件是
(flag_function() = 1 and condition1) or (flag_function() = 0 and condition2)的形式。这两个子条件相互排斥,具体取决于 PL/SQLflag_function()。我注意到 Oracle 在使用UNION ALL而不是使用OR时为此创建了一个更好的计划。PARALLEL可能不会有太大帮助,因为在这种情况下数据量不是很大,但计划很复杂......此外,这个查询在用户会话中运行得非常频繁。我不想用PARALLEL提示占用太多资源 -
这些查询是不等价的。您应该使用 UNION 而不是 UNION ALL。当 x 和 y 都等于 1 的行时,您会得到不同的结果。
-
@GriffeyDog:是的。我知道数据并以它们等效的方式定制查询(具有先验知识)。我会更新问题
标签: sql oracle optimization union union-all