下面这个查询:
查询一:
SELECT * FROM DUAL
等效于并产生相同的结果:
查询 2:
SELECT * FROM DUAL
UNION
SELECT * FROM DUAL
在运行这两个查询之前,这很明显,只需查看它们即可。
然而,甲骨文似乎并不理解这个非常简单的事实,并产生了两个不同的计划:
计划一:
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 |
--------------------------------------------------------------------------
计划二:
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 |
----------------------------------------------------------------------------
这是为什么?两个 UNION-ed 块的简单比较不是比同时执行UNION-ALL
andSORT UNIQUE
操作成本更低吗?或者有没有办法,一个提示,强制 Oracle 在这两种情况下生成相同的计划?
谢谢!
更新
Tnoy 的回答迫使我做更多的实验。结果如下: 当查询与自身进行 UNION 时,较大的查询不一定等同于原始查询。
例如,我创建了一个非常简单的test
表,它只有一列并加载了两个相同的行。
现在,我对这张表的第一个查询是:
SELECT * FROM TEST
返回此结果:
A
-----
2
2
而我的联合查询:
SELECT * FROM TEST
UNION
SELECT * FROM TEST
返回此结果:
A
-----
2
这意味着 Oracle 优化器正在做正确的事情。
谢谢托尼!