はじめに
前回の記事、「データベース設計入門 第1回:そもそもデータベース設計とは何か」では、データベース設計とは何をする作業なのか、そしてどのような流れで設計を進めていくのかを大まかに紹介しました。
データベースを設計するとき、いきなり
「ユーザーテーブルを作ろう」
「注文テーブルにはこのカラムを入れよう」
と考え始めてしまうことがあります。
しかし、本来はその前にやるべきことがあります。
それが、
「このシステムでは、どのようなデータを管理する必要があるのか」を洗い出すこと
です。
システムで必要となるデータは、画面を眺めているだけでは十分に見つけられません。
「誰が利用するのか」
「どのような業務が行われるのか」
「何を登録・変更・確認する必要があるのか」
といった業務要件から、システムで管理すべき情報を整理していく必要があります。
今回は、データベース設計の初期段階で行う「必要なデータの洗い出し」について解説していきます。
この記事の対象者
この記事は、次のような方を対象としています。
- エンジニアとして開発を始めたばかりの方
- SQLは使ったことがあるが、DB設計の経験が少ない方
- 既存のテーブルを使ったことはあるが、自分で設計したことがない方
- 要件からどのようにテーブルを考えればよいのか分からない方
今回は正規化や主キー、外部キーといった具体的なテーブル設計にはまだ踏み込みません。
まずはその前段階として、
「何をデータとして管理する必要があるのか」
を整理する方法を見ていきます。
エンティティとは何か
データベース設計について調べると、よく「エンティティ」という言葉が出てきます。
エンティティとは簡単に言えば、
システムの中で管理したい「もの」や「概念」
のことです。
例えばECサイトを考えてみます。
ECサイトには、次のようなものが登場します。
- ユーザー
- 商品
- 注文
- 支払い
- 配送先住所
これらはすべて、システムの中で情報を管理する必要がある「対象」です。
そのため、エンティティの候補になります。
例えば「商品」であれば、
「どの商品なのか」
「商品名は何か」
「いくらなのか」
「販売中なのか」
といった情報をシステムで管理する必要があります。
この場合、
商品
というものがエンティティです。
データベース設計では、まず業務の中にどのようなエンティティが存在するのかを見つけていくことが重要になります。
属性とは何か
エンティティが「管理する対象」だとすると、その対象が持っている情報を属性と呼びます。
例えば「商品」というエンティティがあるとします。
商品には、
- 商品名
- 価格
- 商品説明
- 在庫数
- 販売状態
といった情報があります。
この一つ一つが商品の属性です。
イメージとしては次のようになります。
商品
├─ 商品名
├─ 価格
├─ 商品説明
├─ 在庫数
└─ 販売状態
同じように、ユーザーであれば次のような属性が考えられます。
ユーザー
├─ 名前
├─ メールアドレス
├─ パスワード
└─ 登録日時
この段階では、まだ「VARCHARにする」「INTEGERにする」といったデータ型まで考える必要はありません。
まずは、
何を管理する必要があるのか
を漏れなく整理することが重要です。
業務要件からデータを抽出する
それでは、実際にどのように必要なデータを見つければよいのでしょうか。
基本的には、業務要件の中に登場する
「名詞」と「業務上必要となる情報」
に注目すると見つけやすくなります。
例えば、次のような要件があったとします。
ユーザーは商品をカートに入れ、注文することができる。
注文時には配送先住所と支払い方法を指定する。
管理者は商品の価格や在庫数を変更できる。
この文章から、まず名詞を拾ってみます。
- ユーザー
- 商品
- カート
- 注文
- 配送先住所
- 支払い方法
- 管理者
- 価格
- 在庫数
ただし、見つけた名詞がすべてエンティティになるわけではありません。
例えば、
「価格」
は商品そのものではなく、商品の持つ情報です。
そのため、
商品
├─ 価格
└─ 在庫数
というように、商品の属性として扱うことが考えられます。
一方で、
「注文」
は独立して管理する必要があります。
誰が注文したのか、いつ注文したのか、注文金額はいくらなのか、といった情報を持つためです。
このように、
名詞を拾う → それが管理対象なのか、管理対象の属性なのかを考える
という流れで整理していくと、必要なデータを見つけやすくなります。
「何を保存する必要があるか」を業務から考える
データを洗い出すときは、
「画面に何が表示されているか」ではなく、「業務として何を記録する必要があるか」
を考えることが重要です。
例えば注文処理を考えてみます。
画面上では、
商品名
数量
価格
合計金額
だけが表示されているかもしれません。
しかし、業務上はそれ以外にも、
- 誰が注文したのか
- いつ注文したのか
- どこに配送するのか
- どの支払い方法を使ったのか
- 注文が現在どの状態なのか
といった情報が必要になる可能性があります。
例えば問い合わせ対応で、
「昨日注文した商品がまだ届いていません」
と言われたとします。
注文日時や配送状況を保存していなければ、確認することができません。
つまり、
現在の画面を作るためだけの情報ではなく、業務を成立させるために必要な情報を考える
ことが重要です。
「画面項目=DB項目」ではない
初心者がDB設計をするときによくある考え方の一つが、
画面にある項目をそのままDBに保存する
というものです。
もちろん画面項目から必要なデータを考えること自体は間違いではありません。
しかし、
画面項目とDB項目は必ずしも一致しません。
例えばECサイトの商品購入画面に、次のような表示があったとします。
商品名:キーボード
単価:5,000円
数量:2
小計:10,000円
このとき、
「小計」
という項目が画面に表示されています。
しかし、
単価 × 数量
で計算できるのであれば、必ずしも小計をDBに保存する必要はありません。
逆に、画面には表示されていなくてもDBには必要な情報もあります。
例えば、
- 登録日時
- 更新日時
- 注文ID
- 商品ID
- 注文ステータス
といった情報です。
これらはユーザーが直接見る項目ではなくても、システムを管理するうえで必要になることがあります。
そのため、
画面にある
↓
DBに保存する
と単純に考えるのではなく、
業務上必要
↓
保存する必要があるか
↓
他のデータから計算できないか
↓
DBで管理する
という考え方をする必要があります。
データの洗い出しは「動詞」から考える方法もある
エンティティを探すときは名詞に注目すると説明しました。
もう一つ有効なのが、
業務で行われる「動詞」から考える方法
です。
例えばECサイトでは、
- ユーザーを登録する
- 商品を登録する
- 商品を購入する
- 注文する
- 支払いを行う
- 商品を発送する
- 注文をキャンセルする
といった処理があります。
ここで、
「注文する」
という処理があれば、
「注文に関する情報を残す必要はないか」
と考えることができます。
また、
「発送する」
という業務があれば、
「発送日時や配送状況を管理する必要はないか」
というデータが見えてきます。
そのため、要件を整理するときは、
誰が
↓
何を
↓
どうする
↓
その結果、何を記録する必要があるか
という順番で考えるのも有効です。
将来必要になりそうな情報をどう考えるか
DBを設計していると、
「将来使うかもしれないから、この項目も入れておこう」
と考えることがあります。
ある程度将来の拡張を考えて設計することは重要です。
しかし、
使うかどうか分からないデータを大量に用意しておくこと
には注意が必要です。
例えばユーザー情報として、
氏名
メールアドレス
電話番号
住所
会社名
部署名
役職
FAX番号
SNSアカウント
などを最初から全部用意したとします。
しかし、現在のシステムで必要なのが
氏名
メールアドレス
だけであれば、残りの項目は使われないままになる可能性があります。
不要な項目が増えると、
- 何のための項目なのか分からなくなる
- NULLの項目ばかりになる
- 入力チェックが複雑になる
- 仕様変更時の影響範囲が増える
といった問題につながります。
そのため、
「いつか使うかもしれない」ではなく、「近い将来どのような要件がある可能性が高いか」
を考えることが大切です。
例えば、
「現在はクレジットカード決済だけだが、今後コンビニ決済も追加する予定が決まっている」
のであれば、複数の支払い方法を扱える構造を考えておく価値があります。
一方で、
「将来、何か別の支払い方法が増えるかもしれない」
程度であれば、必要になった段階で設計を見直す考え方でも問題ありません。
DB設計では、
将来を予言するのではなく、現在分かっている要件と現実的な拡張性のバランスを取る
ことが重要です。
具体例:ECサイトのデータを洗い出してみる
それでは、簡単なECサイトを例にして、実際に必要なデータを整理してみましょう。
次のような要件があるとします。
ユーザーは会員登録できる。
商品一覧から商品を選び、注文することができる。
一度の注文で複数の商品を購入できる。
注文時には配送先住所を指定する。
クレジットカードなどの支払い方法を利用できる。
管理者は商品情報や在庫を管理できる。
まず、業務上登場するものを洗い出します。
ユーザー
商品
注文
注文商品
住所
支払い
それぞれについて考えてみます。
ユーザー
商品を購入する利用者です。
例えば次のような情報が必要になります。
ユーザー
├─ ユーザーID
├─ 氏名
├─ メールアドレス
├─ パスワード
└─ 登録日時
商品
ECサイトで販売する商品です。
商品
├─ 商品ID
├─ 商品名
├─ 価格
├─ 商品説明
├─ 在庫数
└─ 販売状態
注文
ユーザーが行った購入そのものを表します。
注文
├─ 注文ID
├─ 注文したユーザー
├─ 注文日時
├─ 注文状態
└─ 合計金額
ここで重要なのは、
注文と商品を同じものとして考えない
という点です。
一つの注文で複数の商品を購入できるため、注文とは別に「どの商品を購入したのか」を管理する必要があります。
注文商品
注文の中に含まれる商品です。
例えば、
注文番号:10001
キーボード × 1
マウス × 2
USBケーブル × 3
という注文があったとします。
この場合、
注文
だけでは、どの商品を何個購入したのかを表現できません。
そこで、
注文商品
├─ 注文
├─ 商品
├─ 数量
└─ 購入時の価格
といった情報を管理します。
「購入時の価格」を持つ点も重要です。
例えば商品価格が、
注文時:5,000円
現在:6,000円
に変更されたとしても、過去の注文金額は5,000円として残しておく必要があります。
このように、
現在の商品情報だけでは復元できない情報
は、注文時点のデータとして保存する必要があります。
住所
商品を届けるための住所です。
例えば、
住所
├─ 郵便番号
├─ 都道府県
├─ 市区町村
├─ 番地
└─ 建物名
といった情報があります。
ここで、
「ユーザーの住所」と
「注文時の配送先住所」
が必ず同じなのか、という点も考える必要があります。
例えば、
- 自宅
- 勤務先
- 家族の住所
など、注文ごとに別の配送先を指定できる可能性があります。
このような業務要件によって、住所の持たせ方も変わってきます。
支払い
注文に対する支払い情報です。
例えば、
支払い
├─ 対象の注文
├─ 支払い方法
├─ 支払い金額
├─ 支払い状態
└─ 支払い日時
などが考えられます。
最初はクレジットカードだけだったとしても、
- コンビニ払い
- 銀行振込
- 電子マネー
などが追加される可能性があります。
要件として複数の支払い方法を扱うのであれば、
「注文テーブルにクレジットカード情報を直接追加する」
のではなく、
「支払い」という別の管理対象として整理した方がよい場合があります。
洗い出したデータを整理する
ここまでの内容をまとめると、例えば次のようになります。
ECサイト
ユーザー
├─ 氏名
├─ メールアドレス
└─ 登録日時
商品
├─ 商品名
├─ 価格
├─ 商品説明
└─ 在庫数
注文
├─ 注文日時
├─ 注文状態
└─ 合計金額
注文商品
├─ 商品
├─ 数量
└─ 購入時価格
住所
├─ 郵便番号
├─ 都道府県
├─ 市区町村
└─ 番地
支払い
├─ 支払い方法
├─ 支払い金額
├─ 支払い状態
└─ 支払い日時
この段階では、まだ
「何個のテーブルにするのか」
を完全に決定する必要はありません。
まず重要なのは、
業務上必要となる情報を整理すること
です。
最初から完璧に洗い出そうとしない
実際の開発では、最初の要件整理だけですべてのデータを完璧に洗い出せることはほとんどありません。
設計を進めていく中で、
「この情報も必要だった」
「このデータは別で管理した方がよさそう」
「この値は保存しなくても計算できる」
と気付くことがあります。
そのため、
要件整理
↓
データ洗い出し
↓
テーブル設計
↓
不足に気付く
↓
要件・データを再確認
というように、何度か行き来しながら設計していくことになります。
大切なのは、
一度決めた設計を絶対に変えないことではなく、要件との整合性を確認しながら修正していくこと
です。
まとめ
今回は、データベース設計の初期段階で行う「必要なデータの洗い出し」について紹介しました。
ポイントを整理すると、次のようになります。
- エンティティとは、システムで管理する「もの」や「概念」
- 属性とは、エンティティが持つ情報
- 業務要件に登場する名詞からエンティティ候補を探す
- 業務上の動作から「何を記録する必要があるか」を考える
- 画面項目とDB項目は必ずしも一致しない
- 他のデータから計算できる情報は、保存する必要があるか検討する
- 将来使うかもしれないという理由だけで項目を増やしすぎない
- 現在分かっている要件と現実的な拡張性のバランスを取る
DB設計では、いきなりテーブルやカラムを作るのではなく、
「このシステムでは何を管理する必要があるのか」
を整理することが非常に重要です。
ここが曖昧なままテーブル設計を始めると、後になって必要な情報が足りなかったり、逆に不要な項目ばかり増えたりする原因になります。
まずは業務を理解し、必要なデータを洗い出す。
そのうえで、次に
「それらのデータをどのようなテーブルに分けるのか」
を考えていきます。
次回は、今回洗い出したエンティティや属性をもとに、実際にテーブルへ落とし込んでいく考え方について解説します。