6

下面这个查询:

查询一:

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-ALLandSORT UNIQUE操作成本更低吗?或者有没有办法,一个提示,强制 Oracle 在这两种情况下生成相同的计划?

谢谢!

更新

Tnoy 的回答迫使我做更多的实验。结果如下: 当查询与自身进行 UNION 时,较大的查询不一定等同于原始查询。

例如,我创建了一个非常简单的test表,它只有一列并加载了两个相同的行。

现在,我对这张表的第一个查询是:

SELECT * FROM TEST 

返回此结果:

  A
-----
  2
  2

而我的联合查询:

SELECT * FROM TEST
UNION
SELECT * FROM TEST

返回此结果:

  A
-----
  2

这意味着 Oracle 优化器正在做正确的事情。

谢谢托尼!

4

2 回答 2

3

我不是 Oracle 开发人员,但我的猜测是数据库引擎必须先“查看”所有行(UNION ALL查询的结果),然后才能通过执行唯一排序来计算出有多少重复项。

在你的问题结束时你说

...有没有办法,一个提示,强制 Oracle 在这两种情况下生成相同的计划?

我不这么认为,因为您正在尝试执行两个不同的查询。第一个查询是“表中的所有行”,您的第二个查询是要求“表中的所有唯一行”,

即使您没有任何重复,数据库也不知道这一点,并且必须执行排序。

于 2012-10-15T13:48:50.647 回答
2

对于查看查询的人来说显而易见的东西对优化器来说不一定是显而易见的。

UNION语句执行 aUNION ALL后跟 a DISTINCT。尽管数据库优化器可以搜索这种特殊情况(在完全相同的表之间进行联合的查询),但开发人员/经理必须根据优先级做出决定。

在这种情况下确定优化的优先级大概很低。在您的特定示例中,执行计划可能不同,但两者基本上都是即时的(除非您要在循环中为数百万个示例执行此操作)。

于 2012-10-15T14:01:01.300 回答