シェアード・ナッシング・クラスタのスケーラビリティ
シェアード・ナッシング・クラスタにハードウェア・リソースを増強するというのは、一般的には「DBサーバーとそのサーバーからアクセスされるストレージのセットを追加する」という意味になります。
クラスタにリソースを追加して性能が増加するためには、追加したノードのリソースも使用される必要があります。シェアード・ナッシング・クラスタでは表のデータをパーティショニングしてクラスタの各ノードに割り当てます。新しく追加したパーティションを追加したノードに割り当てるか、既存のノードに格納されているパーティショニングした表の一部のパーティションを追加したノードに移し替えます。
ここで、SQL処理によるハードウェア負荷が特定のクラスタ・ノード(DBサーバー+ストレージのセット)だけを飽和させないようにするためには、パーティショニングされた各パーティションへのアクセスがほぼ均等になっていることが求められます。
これはデータベースの表設計において、各表へのアクセス・パターンを解析して適切なパーティション・キーを設定できる必要があります。パーティション・キー設計が適切でないと、アプリケーションからのアクセスが特定のパーティションに偏り、クラスタにノードを追加しても追加したノードが使用されないため性能が向上しないということが起きます。
アプリケーションからの各ノードへのデータ・アクセスが均等になるというパーティショニング設計は1つの表に着目した観点です。しかし、1つのトランザクションは一般的に複数のSQLで構成されており、複数の表にアクセスします。また、SQLのジョインは複数の表が関係します。ジョインする表のパーティションが同じノードに格納されていなければ、異なるノードに格納されている表パーティションのデータをネットワーク越しに取得することになります。
表データへのアクセスが1ノード内で完結する場合よりも、別のノードから表パーティションデータを取得するほうが当然処理時間が増えます。
以上から、シェアード・ナッシング・クラスタにノードを追加して高いスケーラビリティを出すためには、「各パーティションへのアクセス・パターンがほぼ均等になる」「SQL処理による複数表へのアクセスがなるべく1ノード内で完結する」という2つの前提条件を満たすパーティショニング設計が必要になります。
負荷を分散させる表のパーティショニング
シェアード・ナッシング・クラスタの各ノードへのアクセス頻度を適切に分散させるにはまず「各パーティションへのアクセス・パターンがほぼ均等になる」表パーティション・キーを見つける必要があります。オンライン・トランザクション処理でよくあるパターンは、そのシステムのエンド・ユーザーの識別子(ユーザーID)をパーティション・キーにします。これにより、同時に多くのユーザーがアクセスしてきても、複数のノードに処理が分散されることが期待できます。

クラスタにノードを増設し、追加したノードに既存ノードに配置されていた表パーティションを再配分すると、より多くの同時ユーザー数からの処理に対応できる性能向上が期待できます。
1つのノード内にアクセスを完結させる表のパーティショニング
データベースを使用するアプリケーションは1つの表だけへのアクセスで完結するものではありません。
リレーショナル・データベースの表の論理設計ではよく正規化というキーワードが出てきます。正規化はデータの整合性を維持するための各表の論理構造設計の指針となります。
しかし、正規化されたスキーマは、先ほど述べたシェアード・ナッシング・クラスタがスケールするための2つの条件のうち、「SQL処理による複数表へのアクセスがなるべく1ノード内で完結する」を満たすことができません。アプリケーションに関係するすべての表が負荷を分散させるための同じパーティション・キー列を持っているとは限らないためです。
前述した、負荷を分散させるためにユーザーIDの列でパーティショニングした表を考えます。ジョインする表が2つ(表Aと表B)だけであれば、多くの場合パーティション・キー列でジョインするため、両方の表が同じパーティション・キー列を持つことでジョインする対象の行データが同じクラスタ・ノードに格納させることができます。

ここで、ジョインする列がユーザーIDではない処理を考えます。ユーザーID列を持っていない表Cを考えます。表CはユーザーIDをパーティション・キーとすることができないため、別の列をパーティション・キーにすることになります。表AはユーザーID列をパーティション・キーとしてノードと対応付けられていますが、表CはユーザーID列を持っていないため、表Cのパーティションのノードの配置はユーザーIDとは関係ないものになります。そのため、表Aと表Cをジョインすると、表Aの行と同じノードにジョイン対象の表Cの行が格納されているとは限らなくなります。このジョインはノードをまたがって行データを取り寄せる必要があります。シェアード・ナッシング・クラスタのノード数が増えると、表Aと表Cのジョイン対象行が同じノードに格納されている確率が下がります。

この処理を同一ノード内で完結させるための手法には「正規化を崩してすべての表に同じパーティション・キー列を持たせる」「表をパーティショニングして各ノードに排他的に持たせるのではなくすべてのノードに表を複製する」といったものがあります。
これらは、シェアード・ナッシング・クラスタの物理構成に合わせて抽象データ構造を設計する必要があるということを意味しています。これはリレーショナル・データベースのテーブル設計の一般的な手順とは逆です。データの意味的な整合性を取るための正規化を崩す必要が出たり、すべてのノードに複製された表を更新する際にノード間でデータの整合性に影響がないかの検討といった副作用が発生します。
シェアード・ナッシング・クラスタにノードを追加して高いスケーラビリティを出すためには、「各パーティションへのアクセス・パターンがほぼ均等になる」「SQL処理による複数表へのアクセスがなるべく1ノード内で完結する」という2つの前提条件を満たすパーティショニング設計が必要になります。ここでは「同時にアクセスするユーザーが増えるオンライン・トランザクション処理に対処する」ということを仮定しましたが、このアクセス・パターンに特化した物理データ構造にすると、他のアクセス・パターンにはノードを追加しても性能が向上しないということになります。これがシェアード・ナッシング・クラスタが単一目的のためのデータベースとしてしか使われない理由の1つです。
