質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

2回答

2838閲覧

データベースの構造、データの持ち方について

u-sukesan

総合スコア160

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

2クリップ

投稿2020/11/14 02:32

編集2020/11/14 02:36

現在WEBアプリを開発中ですが、
mysqlのデータの持ち方について悩んでおります。

例えば、web上から商品の登録ができるようなフォームがある場合、
商品テーブルには

商品名type1type2type3
商品A食品セット

と登録するしようと思います。

①ここで商品登録フォームのtype1〜type3はselectフォームで選択型にしたいと思っております。
②type1〜type3はそれぞれ、管理画面上で変更追加ができるようにデータベースでデータを持つ
③type1〜type3はそれぞれの値によって変動する動的なフォームではない

そうする場合
タイプテーブルとしてシリアライズして保存した方がいいのか。

type_namecontent
type1a:6:{i:0;s:4:”食品”;i:2;s:4:”雑貨”;i:3;s:6:”消耗品”;}
type2a:6:{i:0;s:4:”個別”;i:2;s:6:”セット”;i:3;s:6:”まとめ”;}
type3a:6:{i:0;s:2:”冬”;i:2;s:2:”夏”;i:3;s:2:”春”;}

それぞれのテーブルを持った方がいいのか

type1_nocontent
1食品
2雑貨
3消耗品
type2_nocontent
1個別
2セット
3まとめ
type3_nocontent
1
2
3

シリアライズした場合、編集や追加、削除がめんどくさいのかな、でも呼び出しはデータベースの1回で呼び出して配列で回せるな
バラバラにすると編集や追加はやりやすいけど、最低3回はデータベースを呼び出す事になる

などどうすればいいか悩んでいます。王道はこうです!とか長所短所などアドバイスをいただけると助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

正規化という単語で調べてみましょう。

他のテーブルに入れるようなデータを、シリアライズ形式でぶっこむようなことは、やむを得ない理由がなければやってはいけません。

投稿2020/11/14 02:51

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u-sukesan

2020/11/14 02:57

ありがとうございます。 正規化するにあたって、データの追加・更新・削除がしにくいシリアライズ化したデータでぶっ込んで置くことは良くない。 という理解でよろしいでしょうか
maisumakun

2020/11/14 03:11

「シリアライズ化したデータでぶっ込んで置くこと」は正規化とは言いません。非正規型です。
u-sukesan

2020/11/14 03:19

なるほど、シリアライズ化したものを入れておくこと自体、非正規化なんですね 理解しました
guest

0

私ならこの例で設計すると、合計4つのテーブルを作成することになりそうですね。
以下、簡単な正規化の例です。

・商品テーブル(merchant)
id(int)
name(varchar)
genre_id(int)
unit_type_id(int)
season_id(int)

・ジャンルテーブル(genre)
id(int)
name(varchar)

・単位テーブル(unit_type)
id(int)
name(varchar)

・季節テーブル(season)
id(int)
name(varchar)

商品情報を取得するときは以下のようなJOINのクエリを用いれば、1回の呼び出しでOKです。
SELECT merchant.name,genre.name,unit_type.name,season.name FROM merchant
LEFT JOIN genre ON merchant.genre_id = genre.id
LEFT JOIN unit_type ON merchant.unit_type_id = unit_type.id
LEFT JOIN season ON merchant.season_id = season.id;

それぞれで名称に変更があった場合も、対応するテーブルのnameを修正すればOKですね。
シリアライズして持っている場合、全商品データを抽出して変更したいデータを含む商品だけを抽出して全部更新する必要が出てきます。
さらに、「食品」に属する商品だけを抽出したい...といった場合、シリアライズして格納されている場合、「食品」というキーワードでLIKE検索するしかなさそうです。(LIKE検索はとても遅い検索なので可能な限り避けたいところ)
上記のような設計であれば、下記のようにジャンルIDを指定した検索で素早く該当商品の一覧を取得できます。
SELECT * FROM merchant WHERE genre_id = 1;

このようなテーブルを設けることで登録画面のフォームを作成する際も、たとえば季節の入力欄はseasonsテーブルの内容を選択肢として表示するようにしておけば、今後追加があればseasonテーブルにデータを追加すれば済みます。
(たとえば季節で「秋冬商品」とか?)

また、テーブル名やカラム名は「TYPE_xx」といった抽象的な単語は使用せず、名前から内容を想像できるものにできればいいですね。

他にもシリアライズだとデータ量が増えたりします。

クエリはJOINする必要があり多少面倒にも感じられるかもしれませんが、正規化してテーブルを分割することをお勧めします。

投稿2020/11/17 07:32

Yith

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u-sukesan

2020/11/17 07:36

ご丁寧な説明ありがとうございいます。 参考になりました。 そうなんです。テーブルを分けること、JOINする負荷など考えると、シリアライズがいいのかなぁなど考えると迷ってしまいます。 頂いた内容と同じような方向で検討しています。
Yith

2020/11/17 07:54

JOINが面倒だから非正規化するのはやめた方がいい場合がほとんどです。 非正規化でいくと今は良くても、後から仕様変更に迫られた場合などに対応に困ることになりがちです。 正規化→非正規化を検討するのは、どうしても正規化してJOINが走るとパフォーマンス的に問題がでる場合ぐらいにしておく方が良いと考えています。 この辺はデータ量やサーバースペックに依存しますが、私の経験ではJOINで困ったことは(めったに)ありません。 インデックスがしっかりしていれば、単純なJOINでパフォーマンスが問題になるケースは少ないと思います。 ただし、インデックス大事です! JOINだけでなく、SQLのパフォーマンス出ないときは、まずインデックス見直してくださいね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問