RGO*_*RGO 5 sql oracle query-optimization union-all
这个查询如下:
查询1:
SELECT * FROM DUAL
Run Code Online (Sandbox Code Playgroud)
相当于并产生与以下相同的结果:
查询2:
SELECT * FROM DUAL
UNION
SELECT * FROM DUAL
Run Code Online (Sandbox Code Playgroud)
在通过查看它们运行两个查询之前,这是显而易见的.
但是,似乎Oracle不理解这个非常简单的事实并产生两个不同的计划:
计划1:
Execution Plan
----------------------------------------------------------
Plan hash value: 272002086
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
计划2:
Execution Plan
----------------------------------------------------------
Plan hash value: 646475286
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 4 | 6 (67)| 00:00:01 |
| 1 | SORT UNIQUE | | 2 | 4 | 6 (67)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
这是为什么?两个UNION编辑的块的简单比较不是比执行这两个块UNION-ALL
和SORT UNIQUE
操作更便宜吗?或者有一种方法,一种暗示,迫使Oracle在这两种情况下生成相同的计划?
谢谢!
UPDATE
Tnoy的回答迫使我做了一些实验.结果如下: 当查询与自身进行UNION编辑时,较大的查询不一定等同于原始查询.
例如,我创建了一个非常简单的test
表,只有一列,并加载了两个相同的行.
现在,我对此表的第一个查询是:
SELECT * FROM TEST
Run Code Online (Sandbox Code Playgroud)
返回此结果:
A
-----
2
2
Run Code Online (Sandbox Code Playgroud)
而我的UNION-ed查询:
SELECT * FROM TEST
UNION
SELECT * FROM TEST
Run Code Online (Sandbox Code Playgroud)
返回此结果:
A
-----
2
Run Code Online (Sandbox Code Playgroud)
这意味着Oracle优化器正在做正确的事情.
谢谢托尼!
我不是 Oracle 开发人员,但我的猜测是数据库引擎必须“查看”所有行(查询的结果UNION ALL
),然后才能通过执行唯一排序来计算出有多少重复项。
在你的问题的最后你说
...有没有一种方法、提示可以强制 Oracle 在两种情况下生成相同的计划?
我不这么认为,因为您正在尝试执行两个不同的查询。第一个查询是“表中的所有行”,第二个查询是要求“表中的所有唯一行”,
即使您没有任何重复项,数据库也不知道这一点,并且必须执行排序。