並列化すれば速くなるのか?
ハードウェアをN倍用意して並列度をN倍にしたとき、並列実行による処理時間は理想的には1/Nになってほしいのですが、実際にはそこまで短縮されません。並列実行を阻害するさまざまな要因があるためです。並列化できない部分や、並列実行プロセスへの負荷の配分が不均一なため最も処理時間の長い並列実行プロセスの完了に引きずられるといった要因です。これら阻害要因の影響をなるべく小さくするようなDBMSのアーキテクチャとデータ構造の工夫が求められます。
ここからは並列実行が効果を発揮するための2つのポイント「処理対象データの均一な分担」と「並列実行プロセスのデータ交換能力の必要性」について見ていきます。
処理対象データの均一な分担
複数ある並列実行プロセスに処理対象データを分担させる必要があるわけですが、大量のデータにアクセスする集計や分析処理の対象になる表は、パーティショニングと組み合わせてパーティション・プルーニングによりアクセス範囲の限定を狙うのが効果的であると第3回で説明しました。
データのパーティショニングを定義していると、DBMSは一般的にパーティション単位で並列実行プロセスに割り当てようとします。ここで、クエリーのアクセスの範囲とパーティショニングの分割アルゴリズムがうまく適合していないと、並列実行プロセス間で処理量の不均衡が生じます。これは特にシェアード・ナッシング・クラスタ構成で問題になります。各ノードに配置するデータの分割定義はパーティショニングの定義そのものです。
データのアクセス範囲を限定するにはレンジ・パーティションやリスト・パーティションが適しています。しかし、アクセスするパーティションを限定するパーティション・プルーニングの考え方と、各パーティション処理の均一化を期待する並列実行の組み合わせはうまくいきません。そのため各パーティションのデータ量を均一化することを目的としたハッシュ・パーティションがあります。ハッシュ・パーティションはパーティション・キーの値をハッシュし、各パーティションがハッシュ・バケットに相当します。全パーティションのデータ個数が均等になることを期待したパーティショニング・アルゴリズムです。
Oracle Databaseはパーティショニングを2階層かけることができます。これをコンポジット・パーティショニングといいます。2階層あるパーティショニングにそれぞれ異なるパーティショニング・アルゴリズムを独立したパーティショニング・キー列で適用することができます。例えば、まずレンジ・パーティションでアクセス範囲を限定したパーティション・プルーニングをかけ、ハッシュ・サブ・パーティションで各サブ・パーティションのデータ量を均一化して並列実行するという使い方ができます。これは後で説明する複数表のジョインの並列化で重要な役割を果たします。
ここまでは各並列実行プロセスの処理時間を均一化することが重要であると説明しました。各並列実行プロセスの処理が完全に独立して実行できればよいのですが、分割されたデータの間に依存関係がある場合があります。例えば複数の表のジョインです。これもパーティショニングと組み合わせると各並列実行プロセスが完全に独立した並列実行が可能になる場合があります。
ジョインする2つの表のジョインに使う列をパーティション・キーとし、各表が同じパーティショニング・アルゴリズムで分割されている場合、片方の表の行とジョインされる相手の行の存在するパーティションはパーティション・キーの定義から確定します。そのため、2つの表のジョインをパーティションごとのジョインに完全に分割して実行することができ、並列化できます。
このように結合列とパーティション・キーが完全に一致しているジョインのことをOracle Databaseではフル・パーティション・ワイズ・ジョインと呼びます。シェアード・ナッシング・クラスタ型のデータ・ウェアハウス向けDBMSでは、各ノードにデータを分散させるアルゴリズムを適用する列を分散キーと呼んだりしますが、結合列と分散キーを一致させるようなチューニングのガイドがあるのはフル・パーティション・ワイズ・ジョインと同じ効果を狙うためです。