6

以下のこのクエリ:

クエリ 1:

SELECT * FROM DUAL 

以下と同等であり、同じ結果を生成します。

クエリ 2:

SELECT * FROM DUAL 
UNION
SELECT * FROM DUAL

これは、2 つのクエリを実行する前に見るだけで明らかです。

ただし、Oracle はこの非常に単純な事実を理解していないようで、2 つの異なる計画を生成します。

プラン 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 で処理された 2 つのブロックを単純に比較すると、 と の両方の操作を行うよりもコストがかからないのではないUNION-ALLでしょSORT UNIQUEうか? または、オラクルに両方のケースで同じ計画を強制的に生成させる方法、ヒントはありますか?

ありがとう!

アップデート

Tnoy の回答により、私はさらにいくつかの実験を行う必要がありました。結果は次のとおりです。 クエリがそれ自体でUNIONされている場合、より大きなクエリは元のクエリと必ずしも同等ではありません。

たとえば、test列が 1 つしかない非常に単純なテーブルを作成し、2 つの同一の行をロードしたとします。

さて、このテーブルに対する私の最初のクエリは次のとおりです。

SELECT * FROM TEST 

この結果を返します:

  A
-----
  2
  2

私のUNION-edクエリ:

SELECT * FROM TEST
UNION
SELECT * FROM TEST

この結果を返します:

  A
-----
  2

これは、Oracle オプティマイザが正しいことを行っていることを意味します。

ありがとうトニー!

4

2 に答える 2

3

私は Oracle の開発者ではありませんがUNION ALL、一意の並べ替えを実行して重複がいくつあるかを判断する前に、DB エンジンはすべての行 (クエリの結果) を「見る」必要があると思います。

あなたの質問の最後にあなたは言います

...両方のケースでオラクルに同じ計画を強制的に生成させる方法、ヒントはありますか?

2 つの異なるクエリを実行しようとしているので、そうは思いません。最初のクエリは「テーブル内のすべての行」に対するもので、2 番目のクエリは「テーブル内のすべての一意の行」を求めています。

重複がない場合でも、データベースはそれを認識せず、並べ替えを実行する必要があります。

于 2012-10-15T13:48:50.647 に答える
2

クエリを見ている人にとって明らかなことは、オプティマイザにとって必ずしも明白ではありません。

UNIONステートメントは、UNION ALLその後に。を続けDISTINCTます。データベースオプティマイザはこの特定のケース(まったく同じテーブル間で結合を行うクエリ)を検索できますが、開発者/管理者は優先順位を決定する必要があります。

この場合の最適化の特定は、おそらく非常に低い優先度です。特定の例では、実行プランが異なる場合がありますが、どちらも基本的に瞬時に実行されます(数百万の例のループでこれを実行する場合を除く)。

于 2012-10-15T14:01:01.300 に答える