並列実行プロセス間のデータ交換能力
ジョインする表が2つの場合、結合列をパーティション・キーにして同じパーティショニング方式にすればフル・パーティション・ワイズ・ジョインになります。しかし現実の処理はジョインする表が3つ以上であり、結合列が異なることがほとんどです。すると、すべての表のジョインをフル・パーティション・ワイズ・ジョインにできるとは限らなくなってしまいます。
フル・パーティション・ワイズ・ジョインできないパターンのジョインも並列化できることが望ましいのですが、これに必要なのが、並列実行プロセス同士がデータ交換をする能力です。ジョインする片方の表がパーティション・キーを結合キーにしてしない場合、並列実行プロセスがジョインの途中でデータ交換できないと、1つの並列実行プロセスは特定のパーティションだけでなく全パーティションを走査しなければならなくなります。これを避けるためには、並列実行プロセスがデータ交換能力を持っている必要があります。
Oracle Databaseでは並列実行プロセスのセットを2つ構成することで並列実行プロセス間のデータ交換能力を実装しています。そのため、並列実行プロセスの個数は最大で水平方向の並列度の2倍になります。並列実行プロセスのセットの間には共有メモリ領域を使用したデータ交換用の小さなバッファ領域を設け、テーブル・キューと呼びます。テーブル・キューを介して並列実行プロセスのセット間でデータ交換が可能になっています。並列実行プロセスのセットは垂直方向のパイプラインを形成し、複雑なSQL実行計画では2つある並列実行プロセスのセットが交互にデータの送信側と受信側の役割を入れ替えていきます。
パーティション方式が異なる表をジョインする場合、並列実行プロセスのセットの片方が表データを分割してスキャンし、それをもう片方の表のパーティション・キーに合わせてテーブル・キューを介して再配分します。MapReduceでいうところのシャッフル操作です。すると、テーブル・キューを介して渡されたデータとのジョインはフル・パーティション・ワイズ・ジョインの形になるので並列実行プロセスのセットはデータ交換なしでジョインできます。
この方法だと、パーティション方式の異なる表のジョインだけでなく、パーティショニングしていない表のジョインの並列化も可能です。
Oracle Databaseでは非パーティション表やパーティション表の1つのパーティションの領域管理単位をセグメントと呼びますが、1つのセグメント内も並列化することが可能です。これは動的なパーティショニングと見ることもできます。
まず、フル・スキャン対象範囲のデータ・ブロック個数を並列度で分割します。そしてそれをさらに大・中・小の3つの範囲(チャンク)に分解します。複数ある並列実行プロセスには大きなチャンクから処理を割り当てていき、処理が終わったプロセスには次に中のチャンクを割り当て、最後に小のチャンクを割り当てます。複数ある並列実行プロセス間でそれぞれのチャンクを処理する時間に差ができたとしても、先に処理が終了したプロセスが次のチャンクを処理するので、最終的な処理時間の差が小さくなるように工夫されています。
