データベース設計アンチパターン

投稿者: | 2022年12月12日

データベース設計に関する技術書を読み漁ったのでアンチパターンについてまとめた。

アンチパターン

単一参照テーブル

構造が似ているマスターテーブルは1つのテーブルに統合すればいいんじゃね?という発想からマスターテーブルという、あらゆるマスター情報を闇鍋にしたクソテーブルのことを単一参照テーブルと呼ぶ

テーブルを水平に分割する

レコードが多くなってパフォーマンスが悪くなったテーブルを二つに分離してしまうパターン

例としては売上テーブルを年度別にテーブルを作ってしまう事。毎年テーブルを作るハメになる上にコーディングも複雑になる。

現在ではパーティションという機能があるので水平分割する利点はない。

テーブルを垂直に分割する

テーブルの列数が多くなって、フォーマンスが悪くなったテーブルを垂直分割するパターン。

例としては社員テーブルを社員会社情報テーブルと社員個人情報テーブルで垂直分割してしまう事。

原則利用すべきではなく、まず下記のデータマートもしくはサマリテーブルで代替を検討する。

データマートとは?

特定の列を抽出したテーブルを作成する手法。例えば社員の誕生日を取得する機能のパフォーマンスを改善したい場合は社員誕生日テーブルを作成すれば良い。

サマリテーブルとは?

計算結果を格納するテーブルを作成する手法。例えば社員の年齢が必要で誕生日から計算する必要ある場合、毎度計算していてはパフォーマンスが悪くなるので、社員年齢サマリテーブルを作成すれば良い。

データマートもサマリテーブルも定期的にバッチを実行して更新する必要があるため注意すること。

可変長文字列をキーとする

当たり前だけど可変長文字列はキーにしてはいけない。名前や部署名は変化するのでキーとしては不適切。

ダブルマスタ

部署Aマスタと部署Bマスタといった全く同じ役割のテーブルが存在するケース。ありえない設計だが、これはシステムの統廃合で発生することが多い。

グレーパターン

代理キーと主キーが役に立たないとき

マスター情報の発生と廃止に伴って主キーが役に立たないことがある。例えば市町村テーブルでは市の統廃合によって、主キーが定まらないことがある。履歴が持たせればよいのでインターバル式にするとよいらしい。

テーブルに履歴管理を持たせるならタイムスタンプよりインターバル

テーブルに履歴管理を持たせるために年月日の列を追加することがある。

タイムスタンプ式とは年月日の列を追加してそれをプライマリキーにする事。

しかし

複合キーにして開始年月日と終了年月日の列を追加して開始年月日をプライマリキーにするのがベスト

終了年月日が未定の場合はnullではなくDateTime.Maxにしておくと開発が楽になる。

テーブルに配列を持たせる

データベースには配列を持たせることができないので、列持ちテーブルか行持ちテーブルで配列を表現できる。

列持ちテーブル

子供1子供2子供3といった列を追加する方法。シンプルだが最大値が決まってしまう上に、無用なNULLが発生する。

行持ちテーブル

配列のインデックス(枝番)列を追加して、それをプライマリキーとするテーブルを作成する方法。

使いどころによっては列持ちテーブルが有用ですが、基本的に行持ちテーブルを採用すべきです。

アドホックキーを追加する

テーブルに集計キーを追加してしまうパターン。その名の通りアドホック(場当たり的)な手法でテーブルにカラムが追加されることでパフォーマンスが低下します。例えば都道府県テーブルが存在し、そこから地方別の集計が必要になったので、地方コード列を追加してしまうケース。県によっては複数の地方コードに該当する例外が存在し、中部地方の県は北陸・東海・甲信越の地方コード、東京都は首都圏と関東の2つの地方コードが該当してしまうので、集計パターンをテーブルに記載するのは悪。

3つの方法で改善できる。

キーを別テーブルに分離する

都道府県と地方に変換するテーブルを用意する。メンテナンスは容易ですが、結合処理が必要なので結局パフォーマンスは悪い。

ビューを使う

地方コードを追加したビューを使う方法。

SQL文で実装する

テーブルも列もビューも用いず、Group By、Where、Having、OrderByなども用いて集計用のSQL文を作成する方法。一番無難。

多段ビュー

ビューを参照するビューを作らないこと。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)