顧客テーブルの属性に毎年、集計データの列を追加するという、ちょっと悪夢のような設計が紹介されていた。テーブルのタブル(行)の長さが変わるというのは運用上、物理的な格納効率を悪化させることがある。また、列が追加されるということは、SQLを実行する際に動的に文字列を組み立てて使う必要がある。Javaならともかく、PL/SQLで動的SQLにそれを使うのはどうか。で、ほとんどの場合は追加した項目が使用されないので、別のことに使おうとしたとかいう記述があるが、それはさらに悪い設計である。
本書にもあるが、データベース管理者によるデータ移行、表領域の再構成などをおこなっていた、と書いている。列追加という対応でなく、テーブルを作り変えていたのは正しい判断だと思う。ただ、あまりにひどい。データ件数が増えて、速度が低下するのを恐れたのだろうか?しかし、それはあまりにひどい対応だ。
ここでは、列ではなく、データ量を減らすために表自体を分けてしまうというのもアンチパターンとしている。列で分けるのは絶対ないにしても、表で分けるというのは比較的見る設計ではある。問題点は以下のとおり。
- テーブルが増殖する。テーブルを作る必要がある。
- 制約の設定の変更が必要になる
- 更新をした場合にテーブルを移動しなければならない場合がある
- テーブルを横断した制約を設定できない
- テーブルを横断した更新などが必要になる
- 属性を追加するような場合に各テーブルに追加しなければならない
- 分割しているテーブルを親とした参照整合性制約を設定することができない
対応策としては、以下のとおり。当然の内容である。
- 水平パーティショニングを使う。つまり、論理的にはひとつのテーブルだが、物理的には複数のテーブルに分割する
- 垂直パーティショニングを使う。列が多い場合は複数のテーブルに分割する。特に使用する頻度や、列の一部のサイズが大きい場合などには有効
- 列を動的に追加するという設計は、おかしいので、テーブルを分割する。
垂直パーティショニングは、データの状況に応じて作るというものもある。例えば、データがエントリされた状況と、承認された状況、実施された状況、完了した状況というように状況が変化することのどれかのタイミングでテーブルを分割することである。
いずれにせよ、分けすぎは良くない。設計者の裁量に任されている。