LoginSignup
mine19876293
@mine19876293 (ミッキー)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

データベース 正規化

解決したいこと

データベースのテーブルをどこまで、正規化していいかわからない!

例)クライアントからの要望

①弊社が実店舗で提供する100種類のプロテインを掲載する
②原材料別(ホエイ、カゼイン、ソイ)で検索できる
③1つの商品に対して原材料は1つである
④会員のみ商品を注文できる
⑤商品注文画面では商品の名前、原材料、価格、画像を確認できる
⑥複数の種類の商品を注文できる
⑦同一商品を複数個注文できる
⑧注文後、注文完了メールが会員に送信される
⑨支払いは商品を受け取った後に別システムで行うので本システムに機能を含めない
⑩データベースを直接触るので管理画面は必要ない

プロテインの購入ができるECサイトを作成する開発案件です。
AmazonのようなよくあるECサイトですが、支払いを行わなくてよいのが特徴的です。

発生している問題・エラー

会員エンティティ 会員ID アドレス パスワード
商品エンティティ 商品ID 商品名 原材料名 価格 商品画像
カート(エンティティ) カートID 会員ID 商品ID 商品個数
注文(エンティティ)注文ID 会員ID 商品ID 商品個数 配送先

自分で試したこと

商品エンティティを正規化すると、商品エンティティは商品ID 商品名
価格エンティティは、商品ID 価格
商品画像エンティティ:商品画像ID 商品画像
原材料エンティティ:原材料ID 原材料名
これが自分なりに正規化した仕様です。あってますでしょうか?

それと、注文エンティティはどこまで、正規化していいかわかりません。

0

5Answer

「正規化」っていう言葉は、DB設計者を「めっちゃテーブル分解できた俺かっこいい」の海に突き落とすのでお気を付けください。

要は、自分でその表(データベース)を管理した時に、管理しやすくなっているかどうかだと思います。
何かをするたびに、あっちもこっちも見に行かなくていいっていうのがいいですよね。

で、見て見ましたが、案の定やりすぎですね。
データがバラバラになりすぎていますし、肝心の紐づけができていません。
仮に紐づけをしたとして・・・

商品テーブル(←エンティティなんて実用性のない言葉は使わない):
商品ID、商品名ID、価格ID、原材料ID、商品画像ID

商品Aの情報を持ってこようとしたら、商品名テーブルと価格テーブルと原材料テーブルと商品画像テーブルを都度都度見に行かなければなりません。
面倒くさいですよね?

ということで、個人的には、

会員エンティティ 会員ID アドレス パスワード
商品エンティティ 商品ID 商品名 原材料名 価格 商品画像
カート(エンティティ) カートID 会員ID 商品ID 商品個数
注文(エンティティ)注文ID 会員ID 商品ID 商品個数 配送先

こっちの方がベターかなと思います。
強いて言うなら、カートテーブルいるかな・・・?保存したいなら必要かな?

0

③1つの商品に対して原材料は1つである

これがのちに反故されるのではという懸念。

世の中にはミックスタイプがある模様
https://www.morinagamilk.co.jp/products/healthfood/miriplus/7781.html
恐らく理由は以下のように吸収効率が異なるから混ぜる人がいる→あらかじめ混ぜたものも用意されている。
https://corporate.kyusai.co.jp/w-protein/chapter4-2.html
ただし、アレルギーや体質に合わないプロテインは除外したいという要求が無いとは思えない

正規化は第三までやってみてあとは仕様や開発効率次第としか言いようがないかと。

0

「クライアントからの要望」が、正規化の話と「プロテインの購入ができるECサイト」の Web アプリで考えるべき話とゴッチャになっていませんか?

例えば、

会員エンティティ 会員ID アドレス パスワード

ですが、ユーザー認証に Web アプリの何らかのフレームワークを使う場合、テーブルの構造は使うフレームワーク側の制約を受け、自由に決められないということもあるはずです。

ASP.NET Core Identity を使う場合、データベースはデフォルトで以下のようになります。

identity.jpg

きちんと分けて考え直した方が良さそうな気がしますけど、いかがですか?

0

エンティティという用語が出てるあたり、ER図でのモデル化と正規化がごっちゃになってそうな気がします。
(おそらく正規化以前にデータモデリングや機能の洗い出しが完了していない)

データモデリング (特に多重度の記載が無くて怪しい)

  • カート:商品は 1:1-* じゃなくてよい?
    (カート1つに対して商品は1種類しか入れられない?)
  • 注文:商品は 1:1-* じゃなくてよい?
  • 商品:原材料は 1:1-* じゃなくてよい?
  • 商品:商品画像は 1:0-* の方がおそらく一般的
  • 価格エンティティ
    普通そんな持ち方はしません。
    少なくとも 商品(商品ID,商品名,価格)あたりは全て商品IDのみで一意に定まりその他どのカラムにも依存しないセットだと思われるので、これ以上分解すべきではありません。
    価格(商品ID,価格) のように分解するのは過剰な正規化として、いわゆる第6正規形というネタ扱いされているやつではないかと。
    そこまで分解して意味があるとすれば、コストかけてでも価格変動を価格履歴(商品ID,価格,タイムスタンプ)として残さねばならないような特殊な前提があったり、非nullである商品名が決まっておらず商品テーブルにinsertできないが商品IDと価格だけを先にテーブルに入れておきたい…という状況(どんな状況??)でDBの制約を回避したい場合などです。
  • 商品画像エンティティ
    前述の多重度の件もあるので、商品画像を独立させることは不自然ではないですが
    画像をどのように保持するのか(DBにバイナリごと入れるのか画像フォルダのパスを指定するのか)にも依ります。
    (本当に商品:画像が1:1で画像パスで指定するなら、商品エンティティに直接持たせた方が妥当かもしれない)
  • 原材料の正規化(別テーブルか名前管理か)
    ※これは本当に正規化の話…… DBで直接変更するスタイルは正規化に弱いが、正規化しないと不整合や表記ゆれに弱い。
    ここは普通正規化しますが、管理画面なしDB直接変更する仕組みで正しく管理するには多少コストがかかります。
  • 注文エンティティが合計金額を持ってなくて危なそう
    ※後述

必要な機能やイベントの洗い出しが済んでなさそう

  • ユーザ操作に基づくもの
    • ユーザ登録・ログイン前にカートを操作できるのか?
      • カートをブラウザ(session/localStorage他)管理 or DB管理 とするかで一長一短ある
    • ユーザは注文の進捗状況とかをサイトから確認できるのか?
      ※後述
    • ユーザは過去の注文をサイトから確認できるのか?
      • 注文確定時点の商品価格とかはどこにも管理しなくてよい?
  • クライアント側担当者の作業に基づくもの
    • 在庫数管理とかしなくてよい?
      • 品切れとか次回入荷未定とかメーカー生産終了etc、サイトの商品ページに表示しなくてよい?
      • 在庫数管理しない場合、品切れのまま注文確定がありえる?
        • 「商品発送しました」とか「次回入荷まで〇日かかります」とか「商品確保できませんでした注文キャンセルまたは一部変更してよいですか」とかがありえるとして
          メールか何かで管理? それともサイト内の注文進捗状況ページなんかでユーザとやりとりする?
          ※後述のイベント管理にも関わる
        • 在庫数管理しない場合、最悪シナリオとしては「品切れのまま注文確定 → メール送信(システムによる自動送信?) → 支払い完了 → 商品の次回入荷が未定 → 返金処理が必要?」
          …とかあるかなと思ったけど、商品到着後に支払いならこれは起こらない?
      • メーカー生産終了した商品情報とかは消す?
        • 過去の注文に関する情報はどれぐらい整合性を保ってDBに保持するのか?
          外部(支払い用別システムとかメール履歴)に頼る前提で全消しする?
      • メーカーとか色々書いたけど、もしもクライアントが自社で製造販売してるのなら問題は起こらない?
        品切れ問題は起こらないとしても、注文確定→原材料確保できないのでやっぱり無理でしたーのリスクは残る?
    • 発送とかのイベント管理
      • 普通は『注文確定 → 発送準備中 or 商品入荷待ち → 発送済み → 入金確認=取引正常終了』とか
        『注文確定 → 商品確保失敗 → 注文キャンセル?(前述の品切れのまま注文確定した場合など)』とか
        のような状況をシステムで一元管理するが、イベント系エンティティは進捗を表すステータスのようなカラムを持たせたり、(イベントID≒今回は注文ID,ステータス,タイムスタンプ) で推移を記録できるようにしたりするモデリングが一般的 ※諸説あります
      • 今回は管理画面も作らない省エネ開発のシステムのようなので、これらの一元管理は別で行う方針?(担当者がエクセル管理したりとかメールで全てを管理したり…?)
    • 注文エンティティが合計金額を持たない弊害
      • 注文確定 → 商品価格見直しとか税率変更 の順番で作業が発生すると問題起こりそう。
        注文確定後に即システムがメール自動送信&前述の通り整合性や履歴は全部外部システム頼りなら、問題はない…?

思いつきで気になった内容をつらつら書いてしまったので、私の記述にも重複や不整合があるかもしれません…

0

余談から始めますが、データモデリングにおいてエンティティの抽出はもう少しまじめにやった方が良いです。
例えば商品エンティティに関しては、価格の変動や商品名の変更といったことを考慮するのが一般的であったりします。

データモデリングの基本を学ぶのにこちらの本が学習を進めるのに大変ためになったので紹介しておきます。
業務別データベース設計のためのデータモデリング入門 -
渡辺 幸三

すげぇ古い本ですがw

で、正規化ですが、すでに指摘があるように第3正規形まで正規化を実施するのが一般的です。
(というより、第3正規形までおこなっておけば間違いが少ないです)
正規化を崩したりその先に進めるのはパフォーマンスや拡張性を検証する中でのチューニングで行われるべきだと考えます。

で、また余談ですが、テーブル設計は正規化のみでは完了しません。
ユーザ情報を保存する時のテーブル設計 - そーだいなるらくがき帳
読むと分かるのですが、エンティティ側からのテーブル設計では無く、運用観点でのテーブル設計になります。
データベースの特性やシステムの挙動も理解していないとできない設計になるので、そこそこ高度な考慮観点になりますが、それでもテーブル設計の基本事項です。

正直質問内容から判断される現状ではまだテーブル設計が出来る段階にないです。
どなたかに実務経験者にサポートを依頼した方が良いですよ。

0

Comments

  1. @mine19876293

    Questioner

    本を購入して、学びたいと、思います。
    貴重な意見をありがとうございました

Your answer might help someone💌