[pgsql-jp: 31228] RE: [pgsql-jp: 31227] テーブルの構造について

Misha misha @ mbm.nifty.com
2003年 10月 18日 (土) 02:48:48 JST


ミーシャです。

私であれば、迷わず、 
 > ・良く使うカラムとそうでないカラムをわけて、複数のテーブルとし、
 >  それを1対1の関係で紐付けるようにして使用する。
を取ります。

カラムの分け方として、確かに「よく使うか使わないか」というのは、
確かに設計の上で好ましいとはいえませんが、
 > ちなみに、私の場合は、今までは、
 > 関連づけられる情報ごとにまとめたテーブルを複数作っていて、
 > 主になるテーブル(従業員の名前が入っているようなマスターテーブル)
 > と1対1でそれぞれを紐付けて使用していました。
とのことであれば、むしろ尚更望ましいと思えます。

PostgreSQL の場合、「追記型」というデータ管理の方式を取っているため、
1カラムでもUPDATEをすれば、その該当レコードはオーバライトされず、
物理的には、新しいレコードがその分だけ追加され、
更新前のレコードは「ゴミ(不要領域)」として残ります。
つまり、相当量のカラムを持つデータであれば、不要領域はかなりのものになります。
(場合によっては、頻繁にVACUUMをかける必要が生じるでしょう)

そもそも、1対1だから、という理由で多くのカラムを1つのテーブルに持たせると、
仕様の変更や追加で、さらにカラムが必要となったとき、大変困ったことになります。
その都度、ALTER TABLE をするという無謀な方法も、「やればできるかもしれない」ですが。
それ以前に、何かの都合で1対多になるケースが生じた場合、最悪、再設計、ということになりかねません。

私の思う最善の方法は、Chieさんのおっしゃるとおり、
関連性の高いコンパクトなテーブルに複数分け、これを1対1で紐付けすることです。
また、あくまで「問い合わせに特化」すると決めごとをした上で、VIEWなどを使うのがよいかと考えます。

 > 一方で、一意の情報を別々のテーブルにわけてしまうというのは
 > 冗長になるというか、構造的によくないような気もしてます。
ちょっと話が脱線気味になりますが、「正規化」、というもの自体がもともと冗長なものですし、
極端にパフォーマンスが落ちるようなケースでなければ、前者はあまり気にする必要はないと思いますし、
「構造的に」という点でいえば、前述のとおり、
長蛇の列を1件のレコードにまとめてしまうほうが、むしろ「よろしくない」と思います。

PHPで
 > pg_affected_rows()で件数の取得ができなかったりしますし。
これは、先の紐付け(分類)の問題になるのでしょうが、
1対1、ということであれば、INSERTやDELETEは無関係で、UPDATEに限った問題ですね。
確かに、いくつかのテーブルを同時に更新した場合、重複した差分が生じてしまいますが、
これも、きれいに分類がされていれば、むしろ、「どれかが更新された」、という情報よりは、
「このカラム(データ)が更新された」と明確に解って、むしろ望ましいのではないでしょうか?
(どうしても「どれかが更新された」としての情報が必要であれば、
予め更新対象の行数を問い合わせておくしかないでしょうが・・・)

-----------------------------------
ミーシャ


> -----Original Message-----
> From: pgsql-jp-admin @ ml.postgresql.jp 
> [mailto:pgsql-jp-admin @ ml.postgresql.jp] On Behalf Of Chie.M
> Sent: Friday, October 17, 2003 7:06 PM
> To: pgsql-jp @ ml.postgresql.jp
> Subject: [pgsql-jp: 31227] テーブルの構造について
> 
> Chieと申します。お世話になっております。
> 
> テーブルを作成していて、迷った事がありまして
> ご相談させていただきます。
> 
> 例えば、従業員管理のテーブルがあったとします。
> このテーブルには従業員の名前や生年月日などユニークな情報を
> 入れるテーブルになっています。
> 
> このような場合、従業員に紐付けされるユニークのデータであれば、
> 一つのテーブルとして扱うのが普通だと思います。
> 
> この時、このテーブルに必要なの情報が沢山あって、
> 一つのテーブルにすると、カラムが200とか300とかになったとします。
> 
> このテーブルはすごく良く使うテーブルなのですが、
> 頻繁に使うカラムは、数百カラムのうち10カラム程度だったとします。
> 
> それ以外のデータは必要ではあるのですが、滅多に使用しません。
> また空欄である場合もかなりあります。
> 
> ここから質問なのですが、このような場合、考え方として
> 下記の2つのどちらがよいのでしょうか?
> (他の案もあれば教えてください)
> 
> ・全てを一つのテーブルとしておく
> ・良く使うカラムとそうでないカラムをわけて、複数のテーブルとし、
>  それを1対1の関係で紐付けるようにして使用する。
> 
> 良く使うテーブルなのに、あまり使わないデータがある大きなテーブル
> というのは、なんとなく重くなりそうな気がしてます。
> 一方で、一意の情報を別々のテーブルにわけてしまうというのは
> 冗長になるというか、構造的によくないような気もしてます。
> 
> ちなみに、私の場合は、今までは、
> 関連づけられる情報ごとにまとめたテーブルを複数作っていて、
> 主になるテーブル(従業員の名前が入っているようなマスターテーブル)
> と1対1でそれぞれを紐付けて使用していました。
> 
> 例えば、
> ・従業員名や部署IDなどが入っている、頻繁に使うテーブル
> ・住所や電話番号、最寄駅や定期代などが入っているテーブル
> ・緊急連絡先などが入っているテーブル
> ・社会保険番号や雇用保険などの保険関係のテーブル
> ・・・
> などのような感じです。
> 
> しかし、このような考え方でいくとテーブルがドンドン増えて
> いってしまう上、使いにくくなるような気もしてきました。
> 
> 私はPHPを使っているのですが、たまに使うテーブルのために
> ビューとルールを作っておいて更新処理などをかけたりすると
> pg_affected_rows()で件数の取得ができなかったりしますし。
> もちろん、PHPでの処理の仕方を変えればいいだけなんですが
> ちょっと不便なかんじです。
> 
> 皆様が開発されるときは、こういう場合はどのように
> 考えますでしょうか?
> 
> 参考までに是非教えていただけると幸いです。
> よろしくお願いします。
> 
> --
> Chie <gontakun_72 @ yahoo.co.jp>
> 
> 
> 


pgsql-jp メーリングリストの案内