マージ結合とは
マージ結合とは、実際にはネステッドループ結合の一種です。結合する2つのデータセットがまだソートされていない場合、データベースはそれらをソートします。最初のデータセットの各行について、データベースは2番目のデータセット内のマッチング行を検出し、前回のイテレーションでのマッチングに基づいてそれらを結合します。これは、ネステッドループ結合とは異なります。ネステッドループ結合では、2番目のデータセットをイテレーションする際に毎回最初の行から始めます。マージ結合の実行疑似コードは以下のとおりです。
for row_1 IN (select * from T1 where xxx)
loop
for row_2 IN (select * from T2 where row_num > last_row_num and xxx)
loop
if match join condition(row_1, row_2)
then
output (row_1, row_2)
else
last_row_num = row_num
break
end if
end loop
end loop
オプティマイザーはいつマージ結合を選択するか
マージ結合は大量データの結合にも適しています。ただし、結合する両側のデータソースが無秩序である場合、または結合条件が非等価結合である場合、オプティマイザーはマージ結合アルゴリズムを選択せず、他の結合アルゴリズムを選択します。それ以外の場合、オプティマイザーはマージ結合計画を生成しようと試み、計画コストに基づいて適切な結合アルゴリズムを選択します。
オプティマイザーによるMerge Joinの使用をどのように制御するか
最も直接的な制御手段は、ヒントを使用して結合アルゴリズムを指定することです。USE_MERGE を使用してオプティマイザーにMerge Joinアルゴリズムを使用させることができます。通常は LEADINGhint も併用する必要があります。これは、Merge Joinアルゴリズムを指定した後でも計画のコストが必ずしも最も低いわけではなく、他のコストの低い計画(結合順序が異なる場合)によって上書きされる可能性があるためです。USE_MERGE のパラメータは結合の右側のテーブルです。
使用例。デフォルトでは、オプティマイザーはHash Joinアルゴリズムを自動的に選択します。
explain select 1 from t1, t2 where t1.c1 = t2.c1;
Query Plan:
======================================
|ID|OPERATOR |NAME|EST. ROWS|COST |
--------------------------------------
|0 |HASH JOIN | |99000 |194200|
|1 | TABLE SCAN|t1 |100000 |41911 |
|2 | TABLE SCAN|t2 |100000 |41911 |
======================================
Outputs & filters:
-------------------------------------
0 - output([1]), filter(nil),
equal_conds([t1.c1 = t2.c1]), other_conds(nil)
1 - output([t1.c1]), filter(nil),
access([t1.c1]), partitions(p0)
2 - output([t2.c1]), filter(nil),
access([t2.c1]), partitions(p0)
オプティマイザーによるMerge Joinアルゴリズムの使用を制御するために、ヒントを使用して制御することができます。
explain select /*+leading(t1 t2) use_merge(t2)*/ 1 from t1, t2 where t1.c1 = t2.c1;
Query Plan:
======================================
|ID|OPERATOR |NAME|EST. ROWS|COST |
--------------------------------------
|0 |MERGE JOIN | |99000 |13200 |
|1 | TABLE SCAN|t1 |100000 |41911 |
|2 | TABLE SCAN|t2 |100000 |41911 |
======================================
Outputs & filters:
-------------------------------------
0 - output([1]), filter(nil),
equal_conds([t1.c1 = t2.c1]), other_conds(nil)
1 - output([t1.c1]), filter(nil),
access([t1.c1]), partitions(p0)
2 - output([t2.c1]), filter(nil),
access([t2.c1]), partitions(p0)
Merge Joinアルゴリズムをより効果的に利用するために、オプティマイザーを制御する際には以下の2点に注意する必要があります:
- データソースが順序付けられている場合は、可能な限りMerge Joinを選択します。
- 非等価結合にはMerge Joinアルゴリズムを使用できません。