查询与其自身的联合生成不同的计划

时间:2012-10-15 13:38:55

标签: sql oracle query-optimization union-all

以下查询:

查询1:

SELECT * FROM DUAL 

等同于并产生与:

相同的结果

查询2:

SELECT * FROM DUAL 
UNION
SELECT * FROM DUAL

在看到它们之前运行这两个查询之前,这是显而易见的。

然而,似乎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 |
--------------------------------------------------------------------------

计划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 |
----------------------------------------------------------------------------

为什么?两个UNION编辑块的简单比较是否比执行UNION-ALLSORT UNIQUE操作成本更低?或者有一种方法,一种暗示,迫使Oracle在这两种情况下生成相同的计划?

谢谢!

更新

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

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

现在,我对此表的第一个查询就是:

SELECT * FROM TEST 

返回此结果:

  A
-----
  2
  2

而我的UNION-ed查询:

SELECT * FROM TEST
UNION
SELECT * FROM TEST

返回此结果:

  A
-----
  2

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

谢谢托尼!

2 个答案:

答案 0 :(得分:3)

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

在你的问题的最后你说

  

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

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

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

答案 1 :(得分:2)

对于查看查询的人来说,显而易见的事情对于优化器来说并不一定是显而易见的。

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

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