JOIN操作は、2つのデータソース(例えばテーブルやビュー)からの出力を結合し、1つのデータソースを返します。複数テーブルのJOINのタイプは、SQLステートメントのWHERE(非ANSI)またはFROM ... JOIN (ANSI) 句で定義されます。FROM句に複数のテーブルが存在する限り、データベースは結合を実行します。
結合条件は、テーブル間の関連関係を定義するために使用されます。ステートメントで結合条件が指定されていない場合、データベースはデカルト結合を実行し、一方のテーブルの各行ともう一方のテーブルの各行をマッチングします。
結合ツリー
結合ツリーは一般的に逆さのツリー構造で表され、以下の図のように、T1 は結合の左側のテーブルであり、ドライバーテーブルとも呼ばれ、通常は次元テーブルです。T2 は結合の右側のテーブルであり、通常はファクトテーブルです。オプティマイザーは通常、左から右の順に結合テーブルを処理します。
結合のデータソースは、別の結合の結果から得られることもあります。左側のデータソースが別の結合の結果から得られ、右側のデータソースがベーステーブルから得られる場合、これを左深ツリーと呼びます。ほとんどの業務計画は左深ツリーです。以下の図のように。
右側のデータソースが別の結合の結果から得られ、左側のデータソースがベーステーブルから得られる場合、これを右深ツリーと呼びます。以下の図のように。
いずれかの結合ノードが他の結合ノードと異なる形状をしている場合、これを密結合ツリーと呼びます。以下の図のように。
オプティマイザーによる結合の最適化
FROM句に複数のテーブルが存在する場合、オプティマイザーは各テーブルペアに対して最も効率的な結合操作を決定する必要があります。オプティマイザーは以下の観点から判断します。
次元 |
説明 |
|---|---|
| ベーステーブルパス | 各ベーステーブルについて、オプティマイザーは主テーブルスキャンやインデックススキャンなど、最適なスキャン方法を選択する必要があります。 |
| 結合アルゴリズム | 2つのデータソースを結合するために、オプティマイザーは2つのデータソースを関連付ける方法を決定する必要があります。利用可能な結合アルゴリズムには、nested loop join、merge join、hash joinがあります。各結合アルゴリズムには効率的な使用シナリオがあり、オプティマイザーは統計情報に基づいて最適な結合アルゴリズムを選択する必要があります。 |
| 結合タイプ | オプティマイザーがサポートする結合タイプには、inner join、left join、right join、full join、left semi join、right semi join、left anti join、right anti join、connect by joinがあります。後者5つの結合タイプはオプティマイザーが再構成したものであり、SQLでは構文指定ができません。 |
| 結合順序 | 結合テーブルの数が2つを超える場合、オプティマイザーは最適な結合順序を決定する必要があります。例:FROM T1, T2, T3 の場合、可能な結合順序には T1 JOIN T2 JOIN T3、T1 JOIN T3 JOIN T2 などがあります。オプティマイザーは可能な結合順序の中から、実行性能が最も優れている結合順序を決定する必要があります。 |
オプティマイザーによる結合計画の決定
結合順序と方法を決定する際、オプティマイザーの目標は結合データ量を早期に削減し、SQLステートメントの実行全体でより少ない作業を実行することです。オプティマイザーは、可能な結合順序、結合方法、利用可能なアクセスパスに基づいて一連の実行計画を生成し、その後各計画のコストを見積もってコストが最も低い計画を選択します。
オプティマイザーは、I/O、ネットワーク、CPUのオーバーヘッドを計算することでクエリ計画のコストを見積もります。異なるデータ配分方法には異なるネットワークオーバーヘッドがあり、さらに異なる関数や式には異なるCPUオーバーヘッドがあります。オプティマイザーはこれらの指標を用いてクエリ計画の総コストを決定します。これらの指標は、PARALLEL、ENABLE_ROWSETS、システム統計情報など、コンパイル時に多くの初期化パラメータやセッション設定の影響を受ける可能性があります。
例えば、オプティマイザーは以下の方法でコストを見積もります:
- ネステッド・ループ結合のコストは、外部テーブルの各行と内部テーブルの各マッチング行をメモリに読み込むコストに依存します。オプティマイザーは内部テーブルの統計情報を使用してこれらのコストを推定します。
- マージ結合のコストは、大部分がすべてのソースをメモリに読み込んでソートするコストに依存します。
- ハッシュ結合のコストは、大部分が結合の入力端の一方でハッシュテーブルを構築し、もう一方の端の行を使用してそれを検索するコストに依存します。