• 検索結果がありません。

• このような特殊な結合タイプは結合順が決まっている

– Oracle Database 10g でハッシュ結合の結合順を改善

実行計画の解説

結合タイプ

アンチ結合

主問合せ 副問合せ

セミ結合

主問合せ 副問合せ

• 左外部結合、右外部結合

– Oracle Database 10g からハッシュ結合で核でないテーブルを先にアクセス可能に

実行計画の解説

結合タイプ(外部結合)

SQL> SELECT … FROM tab1 LEFT OUTER JOIN tab2 USING (c1) GROUP BY … ; 実行計画

---| Id ---| Operation ---| Name ---| Rows ---|

---| 0 ---| SELECT STATEMENT ---| ---| ---|

| 1 | HASH GROUP BY | | |

| 2 | HASH JOIN OUTER | | |

| 3 | TABLE ACCESS FULL| TAB1 | 100K|

| 4 | TABLE ACCESS FULL| TAB2 | 100 |

実行計画(Oracle Database 10gから)

---| Id ---| Operation ---| Name ---| Rows ---|

---| 0 ---| SELECT STATEMENT ---| ---| ---|

| 1 | HASH GROUP BY | | |

| 2 | HASH JOIN RIGHT OUTER| | |

| 3 | TABLE ACCESS FULL | TAB2 | 100 |

| 4 | TABLE ACCESS FULL | TAB1 | 100K|

• 完全外部結合

– Native Full Outer Join ( Oracle Database 11g から)

• 以前は Full Outer Join を二つのブランチの UNION ALL で( Left Outer Join と NOT EXISTS )

実行計画の解説

結合タイプ(外部結合)

SQL> SELECT * FROM tab1 A FULL OUTER JOIN tab2 B USING (c1) ; 実行計画

---| Id ---| Operation ---| Name ---|

---| 0 ---| SELECT STATEMENT ---| ---|

| 1 | VIEW | VW_FOJ_0 |

|* 2 | HASH JOIN FULL OUTER| |

| 3 | TABLE ACCESS FULL | TAB1 |

| 4 | TABLE ACCESS FULL | TAB2 |

<以前は以下のSQLを実行>

SQL> SELECT *

2 FROM tab1 LEFT OUTER JOIN tab2 USING (c1) 3 UINON ALL

4 SELECT * FROM tab2 B WHERE NOT EXISTS

5 (SELECT 0 FROM tab1 A WHERE A.c1 = B.c1) ;

• EXISTS 、 IN 条件の副問合せ

• Oracle Database 10g からセミ・ハッシュ結合で副問合せのテーブルを先にアクセス可能

実行計画の解説

結合タイプ(セミ結合)

SQL> SELECT … FROM tab1 WHERE EXISTS (SELECT 0 FROM tab2 WHERE tab1.c1 = tab2.c1) ; 実行計画

---| Id ---| Operation ---| Name ---| Rows ---|

---| 0 ---| SELECT STATEMENT ---| ---| ---|

| 1 | HASH JOIN SEMI | | |

| 2 | TABLE ACCESS FULL| TAB1 | 100K|

| 3 | TABLE ACCESS FULL| TAB2 | 100 |

実行計画(Oracle Database 10gから)

---| Id ---| Operation ---| Name ---| Rows ---|

---| 0 ---| SELECT STATEMENT ---| ---| ---|

| 1 | HASH JOIN RIGHT SEMI| | |

| 2 | TABLE ACCESS FULL | TAB2 | 100 |

| 3 | TABLE ACCESS FULL | TAB1 | 100K|

• NOT EXISTS 、 NOT IN 条件の副問合せ

– Oracle Database 10g からアンチ・ハッシュ結合で副問合せのテーブルを先にアクセス可能

実行計画の解説

結合タイプ(アンチ結合)

SQL> SELECT … FROM tab1 WHERE NOT EXISTS (SELECT 0 FROM tab2 WHERE tab1.c1 = tab2.c1) ; 実行計画

---| Id ---| Operation ---| Name ---| Rows ---|

---| 0 ---| SELECT STATEMENT ---| ---| ---|

| 1 | HASH JOIN ANTI | | |

| 2 | TABLE ACCESS FULL| TAB1 | 100K|

| 3 | TABLE ACCESS FULL| TAB2 | 100 |

実行計画(Oracle Database 10gから)

---| Id ---| Operation ---| Name ---| Rows ---|

---| 0 ---| SELECT STATEMENT ---| ---| ---|

| 1 | HASH JOIN RIGHT ANTI| | |

| 2 | TABLE ACCESS FULL | TAB2 | 100 |

| 3 | TABLE ACCESS FULL | TAB1 | 100K|

• パーティション・プルーニング

– 静的プルーニングと動的プルーニング(バインド変数、データ型の暗黙変換など)

– パーティションの開始と終了の項目が増える

• Pstart :アクセス開始のパーティション(静的:数字、動的: KEY )

• Pstop :アクセス終了のパーティション(静的:数字、動的: KEY )

• ジェイン・フィルター(ブルーム・フィルタリング)

– 結合列のパーティション・プルーニング

• パーティション化された明細表をマスタ表の条件で検索するなど

この

SQL

のときなどに

明細表

.c1’

でパーティション・プルーニングを行う

実行計画の解説

パーティション

SQL> SELECT … FROM 明細表 A, マスタ1 B WHERE A.c1

= B.c1 AND B.c2 = 'xxx';

実行計画の解説

パーティション(パーティション・プルーニング)

SQL> SELECT * FROM tab01 WHERE sdate = TO_DATE('2012/08/01','YYYY/MM/DD');

実行計画(静的パーティション・プルーニング)

---<途中省略>---| Id ---<途中省略>---| Operation ---<途中省略>---| Name ---<途中省略>---| ---<途中省略>---| Pstart---<途中省略>---| Pstop ---<途中省略>---|

---<途中省略>---| 0 ---<途中省略>---| SELECT STATEMENT ---<途中省略>---| ---<途中省略>---| ---<途中省略>---| ---<途中省略>---| ---<途中省略>---|

| 1 | PARTITION RANGE SINGLE | | | 8 | 8 |

|* 2 | TABLE ACCESS FULL | TAB01 | | 8 | 8 | 実行計画(動的パーティション・プルーニング)

---<途中省略>---| Id ---<途中省略>---| Operation ---<途中省略>---| Name ---<途中省略>---| ---<途中省略>---| Pstart---<途中省略>---| Pstop ---<途中省略>---|

---<途中省略>---| 0 ---<途中省略>---| SELECT STATEMENT ---<途中省略>---| ---<途中省略>---| ---<途中省略>---| ---<途中省略>---| ---<途中省略>---|

| 1 | PARTITION RANGE SINGLE | | | KEY | KEY |

|* 2 | TABLE ACCESS FULL | TAB01 | | KEY | KEY |

バインド変数

データ型の暗黙変換

など

• 結合時に効果的にフィルタリングする(結合列でフィルタリングする)

– ym でフィルターされた time_cd のビットマップを作成する

実行計画の解説

パーティション(ジョイン・フィルター/ブルーム・フィルタリング)

SQL> SELECT * FROM sales_h S, time T

2 WHERE S.time_cd = T.time_cd AND T.ym = TO_DATE('201201','YYYYMM') ; 実行計画

---<途中省略>---| Id ---<途中省略>---| Operation ---<途中省略>---| Name ---<途中省略>---| ---<途中省略>---| Pstart---<途中省略>---| Pstop ---<途中省略>---|

---<途中省略>---| 0 ---<途中省略>---| SELECT STATEMENT ---<途中省略>---| ---<途中省略>---| ---<途中省略>---| ---<途中省略>---| ---<途中省略>---|

|* 1 | HASH JOIN | | | | |

| 2 | PART JOIN FILTER CREATE | :BF0000 | | | |

| 3 | PARTITION RANGE SINGLE | | | 1 | 1 |

|* 4 | TABLE ACCESS FULL | time | | 1 | 1 |

| 5 | PARTITION RANGE JOIN-FILTER | | |:BF0000|:BF0000|

| 6 | TABLE ACCESS FULL | sales_h | |:BF0000|:BF0000|

Time_cdでフィルターを作成

• スキャンのデータ分散

– ブロック単位( PX BLOCK ITERATOR )

– パーティション単位( PX PARTITION RANGE ALL など)

– データ分散しない(片方の読込みデータが少ないとき)

• それぞれの PQ プロセスで全てのデータ

• スキャン以外でのデータ再分散

– PX SEND HASH / RANGE / BROADCAST / PARTITION

• 基本は HASH (重複データが多いときに注意)

関連したドキュメント