miya’s blog

プログラミングの学習を通じて得た知識や感じたことをシェアするブログです。

プログラミングスクールでER図を描いたときに調べたこと

目次

前置き

入会中のプログラミングスクール(フィヨルドブートキャンプ)では、実際のサービスのER図を作成することを通じてデータベース設計の基本を学ぶのですが、指定された参考書だけでは何から描いていいのかピンとこず、少し頑張って調べたのでその内容をまとめました。

  • 対象読者
    • ER図を描きたいプログラミング初学者

データベース論理設計の概要 > 達人に学ぶDB設計 徹底指南書

まずは指定された参考書で、ER図に関係ありそうな箇所をピックアップして調べました。

第2章 概念スキーマと論理設計(P28~33)

  • 論理設計とは、現実世界に存在する数多くのデータを、リレーショナルデータベースにおいて何をどのようなフォーマットで保存するかを決めること。
  • タスクは4ステップ。「エンティティの抽出 → エンティティの定義 → 正規化 → ER図の作成
  • エンティティとは、現実世界に存在するデータの集合体のこと。システムで扱いたいデータを洗い出す。
  • エンティティ定義ではkey列を定義するのが大事。属性=二次元表の列と考えてよい。

第3章 正規化(P84~122)

  • 正規形とは、データベースで保持するデータの冗長性を排除し、一貫性と効率性を保持するデータ形式のこと。
  • 第3正規系まで理解しておけば、ひとまずダイジョブ。第4正規系以後も自ずと満たしていることもザラ。
  • 正規化自体は機械的にできる。論理設計の難しさは正規化が終わってから
  • メンターさん曰く、数件程度のレコードのためにテーブルを切り出すことはあまりないとのこと。(例えば、XX区分など。)

第4章 ER図作成(P123~138)

  • ER図は、Entity-Relationship Diagramの略。描き方に流派は色々あるけど、考え方は大体同じ。
  • ER図を描くときの着目ポイントは、主キーが他のテーブルに列として含まれているかどうか。同じ意味の列をもつテーブル同士の間には3パターンの関係性がある「1対1、1対多、多対多」
    • 1対1:正規化の過程からはでてこない。テーブル間で主キーが一致するなら、普通は一つのテーブルにまとめる。
    • 1対多:最もよくある関連性。0または1も包含する。IE表記法の表記「〇:0, |:1, 千鳥足:2以上」
    • 多対多:リレーショナルデータベースのお約束として作ってはダメ。エンティティ間の主キーを紐づける関連実体を中間に作って表現する。

第5章 論理設計とパフォーマンス(P139~160)

  • ★簡単なER図を描くだけなら一旦スルーでOK!
  • 正規化(= テーブル増 = 結合増)と検索パフォーマンスのトレードオフSQLチューニングではまかない切れない。
  • 非正規化(あえて冗長なデータ構成にする)は様々なトレードオフを知り尽くした上でやるべし。
  • 論理層だけでなく、物理層(ファイル、ハードウェア)の知識がないとパフォーマンスを追求しきれない。

第8章 オートナンバリングの是非(P234~240)

  • 主キーはなぜ必要か?重複コードを許すとパフォーマンスに大きな悪影響があるから。(結合行が冗長に増えないようにする)
  • メンターさん曰く、主キーに自然キーを使うと自然キー自体の仕様変更の影響を大きく受けるので、代理キーを使うことが多いとのこと。

ER図の目的と作り方 > WEB+DB PRESS Vol.130 特集1: 実践データモデリング

「達人に学ぶ~」はエンティティを書きだす部分の説明が少なかったので追加でWEB+DBの特集記事「実践データモデリング」を調べました。

第1章 良いデータモデルの条件

  • データモデルは、業務の概念を関係者全員(ソフトウェアエンジニアだけでなく業務側を含む)が理解し議論できるテキストや図で表されたもの
  • データモデリングの目的は、業務の複雑さを解きほぐし、残存する曖昧さに落としどころをつけて関係者間の共通認識をつくること
  • 良くないデータモデルは、後工程やリリース後に設計の検討漏れや考慮不足が多数見つかる(言われた条件は満たしている。)
  • 良いデータモデルは、モデリングの過程で考慮されていない要求の穴やエッジケースの発見につながる
  • モデル設計のはじめから重視しなくてよいもの
    • 未来の変更内容(予測することは難しい)。a.k.a 変更に強いモデル
    • データを永続化するかどうかの判断と実装方法
  • エンティティは、1つのものを識別するための何らかの識別子が存在し、これに関数従属するいくつかの属性で構成される
  • エンティティの設計は、曖昧で主観的に、業務でどう扱うかを恣意的に定める場合が多い。関係者で対話して、認識を合わせる必要あり。(単一性、同一性、カテゴリ)
  • この特集記事ではER図を用いてデータモデルを表現するが、実際のテーブルやクラスと1対1に結びつくものではなく、あくまでも業務で扱うデータの論理的な表現だとのこと。

第2章 イミュータブルデータモデルとは何か

  • データモデルを複雑にする源泉はデータの更新(UPDATE)
    • 共有リソースの整合性を保つために、更新箇所や更新タイミングを網羅的に把握する必要性が生じる。
    • 初期構築時はなんとかできても時間が経つと不明瞭な箇所が増えていきバグ混入の要因となったり、アプリの保守性が下がっていく。
    • そもそも更新のない設計にできないか?(CRUD図で可視化というレベルではなく)
    • 更新がなければデータのライフサイクルをシンプルで自明にできるはず。
  • 複雑さは、複数の要素が混ざりあうこと。対象を理解しにくく、別のものと組み合わせにくくする。
    • 対義語はシンプル。あるものが1つの責務や1つの役割、1つの概念をもつこと。
    • シンプルさはわかりやすさと変更容易性を生み出す。
    • 問題領域を分割し複雑さに立ち向かいたいけど、分割するとエンティティが増える。エンティティ数の増加も複雑さの一種なので、業務上の結びつきの強いエンティティをグルーピングしながら分割するのが大事。
  • モデリングの出発点
    • システムが扱う情報は、モノ(リソース)コト(イベント)に分類できる
    • イベントは、事業活動において発生した「記録すべき事実」なので更新されてはならない(イミュータブル)。実装においてUPDATEしてはいけないテーブル。
    • リソースは、性質上ライフサイクルがある。属性が変わったり、存在が消滅することもある。実装においてUPDATEしてよいテーブル。
    • 現実的には、全てのイベントのデータの記録や保管には費用コストがかかるので「お金を産み出すもの」と「記録が残らないとお金を失うリスクあるもの」を中心に記録対象を取捨選択する

第3章 イミュータブルデータモデルの基本

  • ステップ1: エンティティを抽出する
    • 要求を文章化し、動詞や名詞に注目する(エンティティと属性の候補)
    • エンティティの定義は、客観的な事実だけでは決められないので関係者で認識を合わせて進める。
    • エンティティの間に関連があれば線で結ぶ。(1対1, 1対多ほか)
  • ステップ2: エンティティをイベントをリソースに分類する
    • 日時属性とは行為の「時点」を表す。(×予定日時、運用開始日)
      • 日時属性を持つ → イベント
      • 日時属性を持たない → リソース
    • イベント発生時には、データが生成されるのみになる
  • ステップ3: イベントには日時属性を1つだけ持つようにする
    • 複数の日時属性を持つなら、別イベントが混ざってる → 分解する
    • 正規化に相当する
  • ステップ4: リソースに隠されたイベントを抽出する
    • リソースに変更日時を持たせたい → 持たせずイベントに抽出
  • ステップ5: 非依存のリレーションシップを交差エンティティで表す
    • 非依存とは、一方が存在しなくても他方は存在し得る関係のこと
    • 交差エンティティは、いくつかのエンティティの関連を表す(関連実体)
  • 詳細は以下URLを参照。おそらく執筆者の公開資料。 scrapbox.io www.slideshare.net

第4章 イミュータブルデータモデルの実践

  • ★簡単なER図を描くだけなら一旦スルーでOK!
  • 現実的なレスポンスタイムを得る等の目的で、イベントがライフサイクル(進行状況、世代管理など)を持つようなモデリングを考える。(ロングタームイベントなど)
  • 詳細は以下URLを参照。おそらく執筆者の公開資料。 scrapbox.io scrapbox.io

第5章 ドメインモデルへの応用

  • ★簡単なER図を描くだけなら一旦スルーでOK!
  • ドメインモデルへの応用をJavaのコードを使って説明。 github.com

ER図の描き方 > Mermaid

ER図作成は、体裁への注文がなかったので、テキスト(Mermaid記法)で書く分だけ修正が容易なVSCode拡張機能Mermaid)を使いました。

mermaid.js.org

ほかの現役生も思い思いのツール(DrawIOとか)を使っていましたが、 メンターさん曰く、手書き📝が手っ取り早いから現場でツールを使うことはあまりないとのこと。

最後に

というわけで、ひとまずER図を仕上げて提出したところ、「複数テーブルで同じデータを保持してるようにみえるけど、どういう意図ですかね?😟セイキカハ? byメンター」とのこと(生兵法はなんとやら...Orz)

イミュータブルモデルまで調べられたのは Good!だけど、今回の課題において

  • 「いつ起きたか」に価値があるイベントはない
  • この規模感(エンティティ5-6個くらい)だとデメリット(コストの高さ)がメリットを上回る

なので、イベント系を考えずリソース系だけで考えてみてくださいと指摘をいただきました。(たしかに特集記事の第2章にそんなこと書いてあったな...🤔)

イベント系を考えるとよいのは

  • 「時系列であらわすことに価値がある」イベントがある場合(例:人事系のシステムにおける異動とか)

で、こういう場合は、論理削除(例:退社とか)が要件に含まれてアンチパターンになることが多いから、これを通常イベントとして扱えると論理削除のデメリットを軽減できる嬉しさがあるとのこと。参考情報として以下URLを教えていただきました。

www.slideshare.net

イミュータブルモデルはSQLアンチパターン「とりあえず削除フラグ」の解決策の一つとして編み出されたモデリング手法だそうです。あと最近聴いているPodcastアーカイブに音声解説に相当するコンテンツがあるのでこちらもどうぞ fukabori.fm

まとめますと

  • ER図はシステムが扱う情報を、モノ(リソース)コト(イベント)に分類して書き出して線で繋ぐ
  • データの論理的な関係性がわかればよいので、ER図自体は基本的にはざっくりな粒度(手書きできるレベル感)で描けばよい。(実装の詳細は不要
  • 高負荷なシステムだと、エンティティの切り出し方は大事っぽい。
  • モデリング(世代管理など)の発想を理解できると役立つ(シンプル化など)機会はあるハズ。
  • データモデルをシンプルにできて直接的に嬉しいのはアプリの開発者や保守者

最後まで読んでいただきありがとうございました🙇🏻

以上