- ベストアンサー
DB+CSV形式での情報サイト開発のデメリットとは?
- PHP+MySQLで情報サイトの開発を行っている際、お客さんからの仕様変更が頻繁にあります。
- 共通項目は20カラムほどあり、非共通カラムは60〜70カラムあります。
- 非共通カラムをCSV形式で管理することを考えていますが、この設計にはデメリットがあります。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
1つの意見として。。 リレーショナルデータベースのカテゴリに書いている以上、「そのデザインでもいい」とは誰も言わないと思いますが、 現実問題として、正規化を進めるほど仕様が固まらない上に、手戻りのコストも負えない以上、そこの部分の正規化はあきらめて進むしかないのでは? CSVと書くと奇異に映りますが、その発想自体は要はXML DBと同じです。リレーショナルの世界でも項目数不定のケースで XMLをテーブルに収録するアプローチは使うことがあります。 このアプローチでデメリットがあるのは、 ・1カラムにどれだけ長いデータが入っても、一部分でも更新するときにはカラム全体を取り出して更新しなくてはならないこと ・整合性・データ型などについて、データベースで保証できなくなること ・範囲検索はもちろん、データに対する一部検索も前方一致以外はできなくなること ・フィールド名にも制約が生じること(住所と自宅住所があったらダメ) ・万一、検索が遅いと言われても打つ手がないこと(インデックスも効かないし) ・後でメンテナンスするのが大変、また蓄積したデータを転用したくなっても容易にできない など。。 別のアプローチとして、テーブル分割はダメなんでしょうか? 属性を自由に追加変更削除できることをウリにしているシステムでは、属性データを縦持ちしているケースも多いです。 メインテーブル (主キー、共通項目、情報タイプなど) サブ項目属性テーブル (項目番号、項目名) サブ項目テーブル (主キー、項目番号、文字、数値、日付) もちろん、個別項目に対する参照整合性は捨てた上でのアプローチであることは変わりませんけど、存在しない属性は登録できないですし、 データ型は保証されます。インデックスも張れますし、検索の柔軟性もかなり上がります(複合検索のクエリがやや書きづらくはなります)。
その他の回答 (3)
- jamshid6
- ベストアンサー率88% (591/669)
#2です。 現在の状況に鑑みればデザインを根本的に変えるつもりはなく、要は誰かに背中を押してもらいたい状態なのかな、と推測しています。良し悪しの判断基準は所詮「今回のシステムで、データベースにどこまでの役割を期待するのか」により変わるものです。 最初から必要最小限の検索とデータ保管庫の役割以上を期待しないのであれば、今のデザインは1つの考え方だと思いますしね。 蛇足になりますが。。 >前方一致「%項目名(%値)%」のほかに後方一致も「%項目名(値%)%」では駄目ですか? これはだめだと思いますよ。質問者さんの例で、 「A(1),B(あいうえお),C(0)・・・・・・」 に対して、「%A(%うえお)%」は通常Trueになります。 >どっちにしてもシステムでデータベースエラーが出るのはまずいのでどのようなシステムを作るにしても入力チェックはPHP側でする必要があります。 データベースの正規化や各種制約の設定は、極論すればアプリケーションがどんな誤作動をしても、データベースが独立した存在として整合性を失わないためにするものだと私は思います。したがって、アプリ側だけでチェックするのも、データベース側だけでチェックするのも本来は不正解です。
補足
>最初から必要最小限の検索とデータ保管庫の役割以上を期待しないのであれば まぁ検索が遅くなった場合は相手にあきらめてもらうしかないですね。 後からいろいろ追加したり言うことが変わってきた代償としてね。 (実際今日もこれ以上追加があるとプログラムの方に入れないし仕様変更ばかりだと作業が遅れるだけです。と昨日の時点でもう一回受元の経由で受注元の方に言ってもらったのですが今日も追加を出してきましたから) >これはだめだと思いますよ。質問者さんの例で、 >「A(1),B(あいうえお),C(0)・・・・・・」 >に対して、「%A(%うえお)%」は通常Trueになります。 確かに言われてみればそうですね。 しかも自分が書いたの前方一致と後方一致が逆になっていたですね。 ただ今回のシステムの場合、検索に必要なのは主に数値そのものの範囲検索(ここは独立カラムにする)とリストボックスやチェックボックスで登録したデータの検索でリストボックスやチェックボックスに関してはValue値は数字だけですからなんとかなると思います。
- hisappy
- ベストアンサー率46% (184/392)
「仕様が完全には確定しない」のと 「動くものを作る必要がある」という状況においては 質問文にある設計は実は最適な解の1つだと思います。 外野の意見となりますが、 そのような暫定的な設計で進行するのであれば PHPであるのを利用して管理コンソール(仮称)のような画面を用意して 本来ならドキュメントに詳細を記載すべき部分を 画面表示させるように対応してみてはどうでしょう。 つまり、これから先の仕様変更におけるDB設計のややこしさを システム側に管理させてることで いわゆる「ドキュメントの不備」を 「コレコレの画面参照」で逃げられる(??)ようにするのです。 応用すると、項目の追加とかリレーションの変更が その管理コンソール(仮称)をウニウニと操作するだけでできるので 稼動後の仕様変更にもコストがドカンでチョコンのボコンと…おっとと。。。 その一方で、「本来の仕様の設計」と 「暫定的仕様の設計」が併走するような格好になるので その点を理解してないと メンテナンスの際に摩訶不思議なロジックに見えてきます。 理想論からいえばそのような設計は駄目なのかもしれませんが、 システムとしては今動かせるものが作れることが大事だと思いますので 併走しながらその手法も成熟させてみるのは良いでしょう。 成功したら一冊本が書けそうな汎用的システムになりそうです。
補足
>応用すると、項目の追加とかリレーションの変更が >その管理コンソール(仮称)をウニウニと操作するだけでできるので >併走しながらその手法も成熟させてみるのは良いでしょう。 納品を遅くとも4月いっぱいでしないといけないのと作業人数も今回はフリーでの仕事で 要求の都度データベース設計を何回もやり直している余裕も無いですし (すでに要求の変更で2回データベース設計をやり直していますし これ以上データベース設計の変更ややり直しに時間がとれないというのもありますけど) そんな細かいエンジンを作る余裕は無いのですが 各タイプごと異なる項目部分で毎回言うことが変わることが多いので 1.各タイプすべて共通部分は独立カラム 2.各タイプで共通項目ではないが検索で範囲指定(数値)が必要な項目は独立したカラム 3.各タイプで非共通なその他の部分に関しては一つのカラム内でCSV形式で管理 って感じになりそうですね。 で1と2の部分と3の部分の判別をテーブル一つ用意して 項目管理テーブル ・主キーカラム:2桁のテキストもしくはtinyint ・独立項目情報カラム:ここもCSV形式で独立させるカラムを書く 例) (主キー00はすべての情報タイプで共通部分として) 00:Uid,Name,Day 01:Number1,Number2 02:Number3,Number5,Number1 03:Number4,Number2 こんな感じでデータベースで管理してそれをPHPに渡して データベース側の独立カラムと一つのカラムにまとめる項目を判断させて入力フォームから入ってきた値を各フォーム項目のNAME属性をそのまま利用して(セキュリティー上データは最低限のエスケープ処理をして)処理する簡易エンジンを作ろうと思っています。
- nora1962
- ベストアンサー率60% (431/717)
> (正規化して共通部分とそうでない部分をわけろって言われそうですが) 私もそう言います。 一旦こういう設計にしてしまうと後々のメンテナンスが大変な上に、検索 の際にパフォーマンスも上がらず、いいことあまり考えられないんですが。
お礼
>検索の際にパフォーマンスも上がらず、いいことあまり考えられないんですが。 実際の所、各カラムを別々にしてインデックスを使わないでやった場合 各カラムを検索させるの自分のやろうとしている方法で 一つのカラムから検索させた場合のパフォーマンスってそんなに変わりますか? 問題はお客さんが昨日と今日で言っていることが変わるし で後から変更になると金額的にもあがりますなど言うと それじゃあ困ると言われるので DB内でCSV方式でデータ管理させれば楽かな?と思ったのです。 問題は数字の範囲指定(不等号)による検索がこのCSVを採用したらできないってことです。(できるなら教えていただければ助かります。) その部分は別途独立したカラムを考えないと駄目ですね。 >メンテナンスが大変な上に 元々70~100項目を7タイプ用意するシステムですので作っているシステム外からメンテナンスをするとなるとメンテナンスは大変なんですよね。 項目が増えたり減ったりしてもこのCSVをカラムに格納するやり方なら DBをいじらずにPHP側の変更だけですみますし
補足
検索に使う項目は独立したカラムにしたとしてそうでない表示だけにしか使わないカラムを一つのカラムにまとめて CSV形式で管理するのはありですよね?
補足
>・1カラムにどれだけ長いデータが入っても、一部分でも更新するときにはカラム全体を取り出して更新しなくてはならないこと 今回のシステムにおいて&更新画面では一通りの項目を出して更新して 変更ある部分と内部分の差分チェックをして更新部分のみUPDATEを発行する予定はありません。 >・整合性・データ型などについて、データベースで保証できなくなること 今回のシステムにおいてデータ整合性をチェックしないといけないのは数値部分だけですね。後はほとんど通常のテキストタイプとリストボックスとチェックボックスですので数字部分はPHP側でctype_digitやis_numericで判別して入力チェックは実装します。 >・範囲検索はもちろん、データに対する一部検索も前方一致以外はできなくなること 各項目部分は「項目名(値)」を利用しますから範囲比較はできなくても 前方一致「%項目名(%値)%」 のほかに後方一致も「%項目名(値%)%」では駄目ですか? >・フィールド名にも制約が生じること(住所と自宅住所があったらダメ) これに関しては各種プロトコルの開始コード/終了コードみたいなものを項目名(値)の頭と最後につけて「^」を制御コードとして使って ^項目名(値)^みたいにすればいいかなって思っています。 そのかわり^は項目名で使えなくはなりますが >万一、検索が遅いと言われても打つ手がないこと(インデックスも効かないし) 検索に使うカラムはよく使いそうな物は個別のカラムとして用意してやるつもりです。 >存在しない属性は登録できないですし、 どっちにしてもシステムでデータベースエラーが出るのはまずいのでどのようなシステムを作るにしても入力チェックはPHP側でする必要があります。