のーずいだんぷ

主に自分用メモですが、もしかしたら誰かの役に立つかもしれません

データベース設計(エンティティ抽出とビジネス的正規化)

はじめに

いくつかの書籍や記事を参考にしながらまともにRDBのデータベース設計をやったのでその備忘録。

使用した書籍は以下。

色々な書籍を並行利用して勉強すると理解が深まるので良かった。

かなり前に勉強した記録が混じっているので未整備だが、後日編集/追記予定で一旦投稿。

基本のき

流れや、知っておくべきことをざっと箇条書きにしてみる。

知っておくべきこと

エンティティには2種類あり、

  • イベント系…動詞化出来るもの(商品購入、 商品出品)、When(タイムスタンプ)をつけられるものかどうか
  • リソース系…複数名詞 かできるもの

がある。

またエンティティの抽出作業については初期段階では網羅的にまずはとにかく書き出すことが重要。

簡単に言うと

  • 発生する作業の一連の流れを思いつくだけ書き出す
  • 各作業について、どんな画面を遷移するかイメージする

正規化

  • オブジェクト指向でもよく言われることだが、テーブルの保持する役割・意味が単一となるような正規化をすること。
  • 一つの事実は一つの場所に
  • ビジネス上における正規化という目線のほうがわかりやすい。データ上重複して見えてもビジネス上ではデータの意味がことなればそれは同じデータとして扱ってはいけない。(重複ではな

プライマリキーの話

業務で使用するコードはプライマリキーにしてはいけない

業務で現在使用されている=ビジネス側の都合で作成したコードは現時点でユニークであって変更可能性が低くても、将来的に変更可能性が生じ問題となるケースが多い。 また複数のコードによる複合プライマリキーしてユニークであること保持している場合も同様で、いずれかのコードに変更があった場合に問題が生じる。

解決策は単なる連番によるプライマリキーを(システム側の意図した識別子で)設定すること。

コード=プライマリキーとすることの弊害

  • 諸々問題(再利用性が低いものをレコードとして保持したくない、もしくはそういう顧客は後に集計したいケースがある)
  • データベースは「事実」を「正しく記録」することが重要!!!!!
    つまりどんなに再利用可能性が低い顧客でも、顧客レコードとしては区別するべき。(それぞれユニークなIDを持つレコードを作成するべき) 後者の、後にそういった顧客をまとめて集計したい場合は別途顧客コード等のカラムで同じIDをふるなどする。databaseはビジネスやプログラム側の要求には引っ張られてはいけない。

  • 対象が計画的モデルの場合

  • 計画的モデル=複数のバージョンが切り替わる(物自体を特定する識別子は必要だが、同時にバージョンを意味するコードには変更が加わる 製品コードをつけるとして、予め変更可能性がある時点でプライマリキーには設定できない。じゃあ仮コードを別途作ってそれを主キーとしても(仮:製品)の2通りのコードしか保持できない。 また製品コードの履歴を管理できなくなる問題もある。
    解決には、製品識別子を外部キーとした製品コード(バージョン)のテーブルを別途作成して、使用期間をカラムとして持たせておく。

その他の問題

  • ある一つのものに対して、複数のコード体系が割り振られている場合
  • コード体系の統一ができるならそれを、(ビジネス側で難しそうであれば)関連エンティティ(m:m)を作成する。
  • 関連エンティティとは異なるコード体系を外部キーとしてまとめたエンティティ(レコード)のこと

データモデルが複雑になることに恐れるな

  • 業務のシステム化を検討する際、多くの場合においてその業務フローや各エンティティの意味付けの多岐化等により、ER図も複雑化するケースが少なくない。 これは仮にデータベース上で複雑さを回避(例えばビジネス上複数の意味合い、もしくはステータスを含むものを単一のエンティティやカラムで管理)した場合、それはプログラム上のswitchやif等の複雑な条件分岐によって判断することになる。対象が複雑である以上、制作するシステムのレイヤのどこかは必ず複雑になる。それがデータに関係する複雑さなのであれば、それはそのまま表現しなければならない。(テーブルの関係が複雑になることは悪ではない)

データのライフサイクルとその後の都合よって生じる問題

  • 一般的にはデータはCRUDのサイクルで最後はDeleteされて、レコードそのものが消失するが個別の要件(そのレコードを参照している別テーブルのレコードがあった場合等)で削除されたと「みなす(ステータスにする)」ケースがある。また、レコードの削除後に識別子の再利用をするケースがあるが、これは過去の(バックアップした)データベースと連結したい場合には、識別子が重複することとなるため虫食いの再利用が推奨されない。