実行計画は, SQL文のレントゲン写真だ! Oracle Database (全部俺)Advent Calendar 2022 Day 3 / No.38 / EXCEPT and EXCEPT ALL Tweet
Day 2は, Oracleの方言である集合演算 MINUS ALL の実行計画というレントゲンを確認しました. MINUSでも19cまでは, ALLはサポートされていませんでした. サポートされるようになった理由は, 今日レントゲンを見ていくEXCEPT/EXCEPT ALLのサポートが影響してそうですね. やることは同じですので:)
では, お約束のw
なお, 今回のSQL文の結果セットはソートされているように並んでいますが, たまたま昇順に並んでいるだけなので, ソートが必要な場合は. 必ず. ORDER BY句を付けてくださいね.
ということで, Day 3の窓を開けましょう!
MINUSは方言ですが, 標準SQLに合わせた形で同様の機能を持つEXCEPTがサポートされました. また, 方言であるMINUSも同様にサポートは継続されています. 下位互換の意味もあると思いますが, MINUS/MINUS ALLの実行計画というレントゲンと比較しながら見ると良いと思います.
いつもと同じように 21c で確認します.
SCOTT@orclpdb1> select banner from v$version;
BANNER
----------------------------------------------------------------------
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Day 1と同じ表とデータを利用します(再掲). 意図的に, 該当表には索引を作成していません.
SCOTT@orclpdb1> @day3
1 SELECT
2 num
3 FROM
4* groupa
NUM
----------
1
2
2
3
4
4
5
7行が選択されました.
1 SELECT
2 num
3 FROM
4* groupb
NUM
----------
0
2
3
3
4
4
4
7
8行が選択されました.
最初は, EXCEPT ALL から診てみます 実行計画を見て〜〜〜〜〜〜くださ〜〜〜〜い, 驚きますよ!!!!
内部では, MINUS ALL に書き換えられている!! これが MINUS ALLをサポートした理由ですねw やってることが同じなので, まあ無駄が無いのは確かだw
EXCEPT ALLが内部で, MINUS ALLに書き換えられているのでしょうか. 今回はトレースを取得して追いかける余力はないので, その辺りは別の機会にでも.
また, このケースでもHASH操作が現れています.
1 SELECT
2 num
3 FROM
4 groupa
5 EXCEPT ALL
6 SELECT
7 num
8 FROM
9* groupb
NUM
----------
1
2
5
実行計画
----------------------------------------------------------
Plan hash value: 895579533
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 45 | 8 (25)| 00:00:01 |
| 1 | MINUS ALL HASH | | | | | |
| 2 | TABLE ACCESS FULL| GROUPA | 7 | 21 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| GROUPB | 8 | 24 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets
0 physical reads
0 redo size
648 bytes sent via SQL*Net to client
52 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3 rows processed
次は, EXCEPT 同様に, HASH操作を伴うMINUSとして現れています. やっている集合演算も同じですから, 実行計画だけ見せられたら, EXCEPTなのかMINUSなのかは区別できないでしょうね. 区別する必要もないわけですけども.
プロジェクトのSQL標準がどちらを使うか定めていれば, どちらかなのかは想像できるかも知れませんがw
1 SELECT
2 num
3 FROM
4 groupa
5 EXCEPT
6 SELECT
7 num
8 FROM
9* groupb
NUM
----------
1
5
実行計画
----------------------------------------------------------
Plan hash value: 2352437695
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 45 | 8 (25)| 00:00:01 |
| 1 | MINUS HASH | | | | | |
| 2 | TABLE ACCESS FULL| GROUPA | 7 | 21 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| GROUPB | 8 | 24 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets
0 physical reads
0 redo size
640 bytes sent via SQL*Net to client
52 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
次に, 索引アクセスがある場合はどうなるかを確認します. 利用するデータや表はDay1と同じです.(再掲) なお, 索引等の情報は前回のエントリーをご覧ください
1 SELECT
2 unique_id
3 FROM
4 tab311
5 WHERE
6* unique_id BETWEEN 1 AND 50
UNIQUE_ID
----------
1
1
1
2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
53行が選択されました.
1 SELECT
2 unique_id
3 FROM
4 tab312
5 WHERE
6* unique_id BETWEEN 25 AND 75
UNIQUE_ID
----------
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
51行が選択されました.
まずは, EXCEPT ALLから Table Full Scanであろうが, Index Range Scanであろうが, HASH操作になる点も含め, MINUS ALLそのものですね:)
1 SELECT
2 unique_id
3 FROM
4 tab311
5 WHERE
6 unique_id BETWEEN 1 AND 50
7 EXCEPT ALL
8 SELECT
9 unique_id
10 FROM
11 tab312
12 WHERE
13* unique_id BETWEEN 25 AND 75
UNIQUE_ID
----------
1
1
1
2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
27行が選択されました.
実行計画
----------------------------------------------------------
Plan hash value: 381125746
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 50 | 612 | 8 (25)| 00:00:01 |
| 1 | MINUS ALL HASH | | | | | |
|* 2 | INDEX RANGE SCAN| TAB311_PK | 50 | 300 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN| IX01_TAB312 | 52 | 312 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("UNIQUE_ID">=1 AND "UNIQUE_ID"<=50)
3 - access("UNIQUE_ID">=25 AND "UNIQUE_ID"<=75)v
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
1040 bytes sent via SQL*Net to client
63 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
27 rows processed
EXCEPTの実行計画という名のレントゲンはどうでしょう?
思った通り MINUS と同じ実行計画が現れています
1 SELECT
2 unique_id
3 FROM
4 tab311
5 WHERE
6 unique_id BETWEEN 1 AND 50
7 EXCEPT
8 SELECT
9 unique_id
10 FROM
11 tab312
12 WHERE
13* unique_id BETWEEN 25 AND 75
UNIQUE_ID
----------
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
24行が選択されました.
実行計画
----------------------------------------------------------
Plan hash value: 2829086308
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 50 | 612 | 8 (25)| 00:00:01 |
| 1 | MINUS | | | | | |
| 2 | SORT UNIQUE NOSORT| | | | | |
|* 3 | INDEX RANGE SCAN | TAB311_PK | 50 | 300 | 3 (0)| 00:00:01 |
| 4 | SORT UNIQUE NOSORT| | | | | |
|* 5 | INDEX RANGE SCAN | IX01_TAB312 | 52 | 312 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("UNIQUE_ID">=1 AND "UNIQUE_ID"<=50)
5 - access("UNIQUE_ID">=25 AND "UNIQUE_ID"<=75)
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
9 consistent gets
0 physical reads
0 redo size
993 bytes sent via SQL*Net to client
63 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
24 rows processed
19cでは, EXCEPT/EXCEPT ALLともに未サポートなので, どちらもシンタックスエラーです. 当然と言えば当然の結果です:)
SCOTT@orcl> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
1 SELECT
2 unique_id
3 FROM
4 tab311
5 WHERE
6 unique_id BETWEEN 1 AND 50
7 EXCEPT ALL
8 SELECT
9 unique_id
10 FROM
11 tab312
12 WHERE
13* unique_id BETWEEN 25 AND 75
EXCEPT ALL
*
ERROR at line 7:
ORA-00933: SQL command not properly ended
1 SELECT
2 unique_id
3 FROM
4 tab311
5 WHERE
6 unique_id BETWEEN 1 AND 50
7 EXCEPT
8 SELECT
9 unique_id
10 FROM
11 tab312
12 WHERE
13* unique_id BETWEEN 25 AND 75
EXCEPT
*
ERROR at line 7:
ORA-00933: SQL command not properly ended
まだまだ, Day 3 ですねーーーーw
意外に多くの, ITアドベントカレンダー全部俺, または, 準全部俺(タイトルに全部俺って書いてないだけで, 多分, 全部俺になっちゃうでしょうーーっなカレンダー立てた方含め,
楽しんでやってきましょう. w
明日の Day 4の担当は, なんとーーーっ, 私ですw
では, また.
参考)
19c UNION [ALL], INTERSECTおよびMINUS演算子
Related article on Mac De Oracle
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 1 / TABLE FULL SCAN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 2 / INDEX UNIQUE SCAN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 3 / INDEX RANGE SCAN, Index Only Scan
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 4 / INDEX RANGE SCAN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 5 / INDEX RANGE SCAN, INLIST ITERATOR
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 6 / INDEX FAST SCAN, Index Only Scan
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 7 / INDEX FULL SCAN,Index Only Scan
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 8 / INDEX SKIP SCAN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 9 / TABLE ACCESS INMEMORY FULL
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 10 / NESTED LOOP JOIN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 11 / MERGE JOIN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 12 / HASH JOIN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 13 / HASH JOIN OUTER
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 14 / HASH JOIN FULL OUTER
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 15 / PX, TABLE ACCESS FULL
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 16 / CONCATENATION
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 17 / SORT UNIQUE, UNION-ALL = UNION
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 18 / UNION-ALL
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 19 / INTERSECTION
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 20 / MINUS
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 21 / WINDOW NOSORT STOPKEY
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 22 / COUNT STOPKEY
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 23 / HASH JOIN - LEFT-DEEP JOIN vs RIGHT-DEEP JOIN
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 24 / CONNECT BY NO FILTERING WITH START-WITH
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - Day 25 / UNION ALL (RECURSIVE WITH) DEPTH FIRST, RECURSIVE WITH PUMP
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#1 / STAR TRANSFORM, VECTOR TRANSFORM (DWH向け)
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#2 / MERGE (UPSERT)
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#3 / RDFView
・実行計画は, SQL文のレントゲン写真だ! Oracle Database編 (全部俺)Advent Calendar 2019 - おまけ#4 / INDEX FULL SCAN (MIN/MAX) - Index Only Scan
・実行計画は, SQL文のレントゲン写真だ! No.30 - LOAD TABLE CONVENTIONAL vs. LOAD AS SELECT
・実行計画は, SQL文のレントゲン写真だ! No.31 - TEMP TABLE TRANSFORMATION LOAD AS SELECT (CURSOR DURATION MEMORY)
・実行計画は, SQL文のレントゲン写真だ! No.32 - EXTERNAL TABLE ACCESS FULL / INMEMORY FULL
・実行計画は, SQL文のレントゲン写真だ! No.33 - BITMAP CONVERSION TO ROWIDS
・実行計画は, SQL文のレントゲン写真だ! No.34 - 似て非なるもの USE_CONCAT と OR_EXPAND ヒント と 手書きSQLのレントゲンの見分け方
・実行計画は, SQL文のレントゲン写真だ! No.35 - 似て非なるもの USE_CONCAT と OR_EXPANDヒントとパラレルクエリー
・実行計画は, SQL文のレントゲン写真だ! Oracle Database (全部俺)Advent Calendar 2022 Day 1 / No.36 / INTERSECT ALL
・実行計画は, SQL文のレントゲン写真だ! Oracle Database (全部俺)Advent Calendar 2022 Day 2 / No.37 / MINUS ALL
| 固定リンク | 0
コメント