ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

MySQLコミュの配列やオブジェクトの扱いについて

  • mixiチェック
  • このエントリーをはてなブックマークに追加
フィールドのデータ型として、配列やオブジェクトなどの可変長データを保存したい場合、どう扱うべきなのでしょうか? とりあえず、私なりに 2 つの対策法を考えてみたのですが、合理的・常識的に妥当な実装はどちらなのでしょう。もちろん、他にも美しい方法があれば、是非ご教授願いたいと思います。何分ド素人なもので、常識に欠けている面も否めませんが、何卒宜しくお願い致します。( MySQL5.0 を想定)

【1】文字列に変換して TEXT 型で保存
唯一の可変長データ型である文字列型を使う方法です。単純な配列ならば、'1,2,3,・・・' というように区切り文字を挟んだ展開で実現できます。PHP でいうところの、implode ⇔ explode を使った 結合⇔分解 ですね。ちなみに PHP には、オブジェクトを含めてオールマイティに対応できる serialize ⇔ unserialize という関数がありました。

【疑問】フィールドはオブジェクトに束ねるべきか?
検索やソートに用いない、ただデータを保持する為だけのフィールドは、出来るだけ連想配列やオブジェクトにまとめて、一つのフィールドに押し込んでしまった方が良いのでしょうかか? もっとも数値型などは文字化されてデータ量が増えるでしょうし、アクセスが多少困難になりますが、レコード毎に自由に要素を設定できるので、利点も多いように感じます。それとも、余りオブジェクトを肥大化させると、復号コストが響いて効率性を欠いてしまうのでしょうか?

【2】レコード毎にテーブルを生成して関連付ける
テーブルを 2 次元配列として用いる方法です。レコード毎に独自のサブテーブルを生成して、ID か何かでリンクさせれば、簡単にデータベースという配列を持たせることができます。もちろんサブテーブルのレコードにリンクさせて"サブサブ"テーブルを再帰的に作っていけば、多次元配列も表現できるでしょう。もっとも、これでオブジェクトを表現すると非効率な気がしますが、配列に特化するなら、要素数が多くなると【1】より効率的な気がします。

【疑問】膨大な数のテーブルを生成してよいものなのか?
レコードの数に比例してサブテーブルの数が増えるため、管理が難しくなるかもしれません。特に多次元配列となると凄まじいことになりそうです。膨大なテーブルの乱立は、データベースとしての効率性を低下させる要因にもなり得るのでしょうか? それとも、ツリー構造のように階層的に管理できるテーブルを作ることが可能なのでしょうか?

・implode: http://jp.php.net/manual/ja/function.implode.php
・explode: http://jp.php.net/manual/ja/function.explode.php
・serialize: http://jp.php.net/manual/ja/function.serialize.php
・unserialize: http://jp.php.net/manual/ja/function.unserialize.php

コメント(11)

テーブル設計時の正規化と正規化を崩す話のようなきがします。

基本的には、データベース設計でテーブルを正規化する段階で各テーブル・項目に振り分けます。
ただし、それにより性能が満たせないような場合、『最後に』正規化を崩して性能要件を満たすようにする場合があります。
# RDBMSでの膨大って、1億レコードとか、1000テーブルとかですか?MySQLにとっては、もっと小規模でも膨大なのかもしれませんが・・・それは適材適所。規模に合わせてMS SQL Server ExpressやOracleXEなどの利用も考えます。

なお、その項目を個別に検索しない場合(常に1度に取り出して1度に更新する場合)には、1項目にまとめることもできるわけですが、その場合には、「他の言語からアクセスする可能性が今後一切無いのか?」を考えて決定します。
・他の言語からの利用がありえないなら、serialize。phpにもJavaにもpythonにもありますし(もちろん非互換)、連想配列や複雑な構造もそのまま出し入れ可能。
・他の言語からの利用もあるのであれば、書式を決めて変換します。CSVかTSVか固定長レコードのいずれかを使用することが多いです。
※XMLで格納することで、そのまま検索の対称にすることができるRDBMSもあります。
データベースをPHPのような手続型の言語と同じように考えているんじゃないですか。
基本的にはデータベースのカラムには1つの事実を、というのが本来だと思います。
データモデリング、データベース設計の書籍からまず基本を読まれることをお勧めします。
シンプルな構成で組み立てられないなら仕方ないですが、何も仕様を敢えて複雑化することもないと思います。
RDBMSでオブジェクトを扱うということ自体が間違っているんじゃないでしょうか?
シリアライズしてデータをいれたとしても、中のデータのリレーションも何もなくなるので、それこそ単なるネットワークストレージみたいなものです。
自分が使用したことが無いので、実用性は分かりませんが、ODBMSを使ってみるのはどうでしょうか?

なお、設計の仕方や資源にもよりますが、MySQLは、数億レコード、数千テーブル程度であれば、実用的なレベルで動作します。
ただし、テーブルの数が、数百にもなると、クライアント接続時の"--auto-rehash"にかかる時間が非常に長くなり、"--no-auto-rehash"で接続できない一部クライアント(navicat等)でまともに接続できなくなる等、管理上の問題がいろいろ出てきます。

ただ、多次元配列くらいであれば、単テーブルで表現できると思いますけどね。
こうしたらどうでしょうか?
タテ展開というものです。

http://xoops.sourceforge.jp/wiki/xoops2/index.php?%C7%F2%C0%F0%B8%E5%B7%D1%A5%E2%A5%B8%A5%E5%A1%BC%A5%EB%A5%C7%A1%BC%A5%BF%A5%E2%A5%C7%A5%EB

理論上はたて展開のみですべてカバーできるのですが、
それではあんまりなんで、シリアライズいれています。
>>>>> うぇいく さん
>正規化と正規化を崩す話
はい、まったくその通りでした。(>_<) 今更慌てて正規化を勉強し始めたのですが、確かに真逆の要求だったのですね。

>『最後に』正規化を崩して
なるほど、やはり正規化では満たせない要求というのもあるのですね。しかしあくまでも正規化した上で、"崩し"を最小限に抑えるという方針が必要になると。勉強になりました。

> RDBMSでの膨大って、1億レコードとか、1000テーブルとかですか?
すみません、レベルの低い話で。(^_^;) レコード毎にテーブルを作ったらゴチャゴチャして大変だなぁという程度のイメージです。

> 規模に合わせてMS SQL Server ExpressやOracleXEなどの利用も考えます。
突き詰めると、システムとしての許容量も重要になってくるのですね。興味深いです。

>「他の言語からアクセスする可能性が今後一切無いのか?」を考えて決定します。
確かに互換性を考えないと問題がありますね。とりあえず今回は PHP での利用を想定していますが、今後も常に考慮すべき重要事項と心得ました。

> XMLで格納することで、そのまま検索
確かに調べてみると、RDBMS 意外にもいろいろなデータベースがあるのですね。MySQL ばかりに目が行っていましたが、それらの利点欠点を踏まえて検討すべく、さらに見識を深めていきたいと思います。
>>>>> masahiko さん
>手続型の言語と同じように考えているんじゃないですか。
はい、お恥ずかしながら"リレーション"の言葉が頭から離れていました。(^_^;) 概念の切り替えが上手く出来なかったようです。

> 基本的にはデータベースのカラムには1つの事実を、
なるほど、データベースとしての概念を踏襲すれば、確かにおっしゃるとおりですね。心掛けたいと思います。

> まず基本を読まれることをお勧めします。
はい、PHP からの操作に関する初歩の話ばかり読んでいて、データベースとしての基本を押さえていない未熟さが身に染みました。早速 MySQL 専門の本を買ってきたので、基本的な常識を養いたいと思います。
>>>>> K.Matsudo さん
> RDBMSでオブジェクトを扱うということ自体が間違っている
はい、まさしくそうでした。考えてみれば"関係"ですものね。(>_<) バカ丸出しでした。配列を無くすこと自体が"第一正規形"なんですものね。

> それこそ単なるネットワークストレージみたいなものです。
はい、正直ストレージのイメージが拭えませんでした。(^_^;) まったく勘違いもいいとこです。失礼しました。

> ODBMSを使ってみるのはどうでしょうか?
早速調べてみたところ、確かに僕の要求にはぴったりなデータベースのようですね。オブジェクトベースの概念があったというのは驚きでした。すぐには手が出せないかも知れませんが、有用な方式としてこれからも勉強していきたいと思います。

> 管理上の問題がいろいろ出てきます。
テーブルの乱立はまずいだろなぁと漠然とはイメージしていましたが、システム上の問題出てくるという点は重要ですね。貴重なお話、ありがとうございます。

> 多次元配列くらいであれば、単テーブルで表現できると思いますけどね。
そう言われれば確かに、すべての要素は同じ構造なのですから、レコードの関係性だけを定義すれば、単一テーブルで自由に多次元を作れますよね。勉強になりました。
>>>>> へむー さん
>レコードごとにテーブルを作るのは机上でも現場でもまず無いですね。
やはりそうですよね。(^_^;) 僕も正直恐ろしかったです。

>まずデータの正規化をすることが必要です。
はい、重要性が身に染みました。

>一つのフィールドにまとめることは私もよくやります。
正規化の上での末端の統合は、有効な方法なのですね。非常識なのかなとも思ったのですが、皆さんのお話を聞いて安心しました。とりあえず、なにはともあれ、まずは正規化ですね。

> 検索に使う場合は 区切り文字の選び方、付け方には熟慮しなければなりません。
うぇいく さんの互換性の話にも通じますが、確かに検索対象にするとやっかいですよね。特にオブジェクトとなると文法が複雑そうですし。後々の変更が困難な分、入念に設計しないとだめですよね。頑張ります。
>>>>> tadashi さん
>タテ展開というものです。
なるほど、目が鱗といった感じです。(^ ^) 正規化との兼ね合いが難しそうですが、昔からある方法のようですし、オブジェクトの表現形式としては有用ですよね。勉強になりました。

・Yahoo曰く、XMLじゃなくてPHPの変数をそのままシリアライズして返せばいいじゃん: http://neta.ywcafe.net/000544.html

それにしても、"シリアライズ"というのも深い話なんですね。XML などの規格や構造もいろいろあるみたいですし、うぇいく さんも述べられているように、データベースに使うなら使うで、設計をキチンしなくてはならないと。うーむ、難しいです。
お忙しい中、様々なご意見をありがとうございました。早速、実際の開発に生かしたいと思います。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

MySQL 更新情報

MySQLのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング