マージ結合とは
マージ結合は、厳密にはネストされたループ結合の一種です。結合する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アルゴリズムの使用を指示できます。通常は LEADING ヒントも併用する必要があります。これは、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アルゴリズムを使用できません。