テーブル内容は、記事のタイトル名、投稿日時などの一覧テーブルA、もう一つは、その一覧テーブルと紐付けされた投稿記事本文を格納するテーブルBで下記のようになります。
テーブルA: タイトル名,投稿者名,投稿日時,テーブルBの本文ID
テーブルB: 本文ID,記事本文
テーブルAは投稿内容を一覧表示する際に単体でも使われます。
上記2つのテーブルを下記のように一つにまとめ、
テーブルC: タイトル名,投稿者名,投稿日時,記事本文
このテーブルCで投稿内容の一覧を表示したい場合、タイトル名,投稿者名,投稿日時にインデックスをはっておけば、テーブルA単体時と同等の速度がでるものなんでしょうか(もちろん、テーブルAも同じカラムにインデックスをはっているものとします)。
ちなみに数万件単位の投稿でInnoDBを使用した想定をしており、テーブルをまとめることのメリットとデメリットを教えて下さい。よろしくお願いします。
1つにまとめると、2つのテーブルを扱うよりも手順は楽になりますが、
記事が増えるにしたがって劇的に遅くなる可能性があります
レコード長が劇的に長くなっているため、
メモリ上のバッファに格納できるレコード数が大幅に減少し、
ハードディスクへのアクセスが増え、遅くなるという流れです
しかしながら、たかだか数万件規模なので、
パソコンをそのシステム専用に使う場合は無視できるかもしれません
共有サーバなどになれば利用できる物理メモリなどが限られてくるので、
問題が顕著にあらわれてくることもあるでしょう
結合はいつでもできますが分離は面倒です
私は分けたままにしておくことを勧めたいですね
まず確認。テーブルAの1レコードとテーブルBの1レコードは1対1対応?
1対1であればまとめた方がよい。
管理性もあるが、JOIN のコストが馬鹿にならないのでテーブルBの情報を参照するときに明らかに遅い。
このテーブルCで投稿内容の一覧を表示したい場合、タイトル名,投稿者名,投稿日時にインデックスをはっておけば、テーブルA単体時と同等の速度がでるものなんでしょうか
SELECT 文で元々テーブルAに存在したカラム名のみ指定しておけば速度的なデメリットは殆ど無い。
数万件程度ならなおさら。
ただ、このあたりは実際に入っているデータやアプリケーションからの参照と更新の度合いによっても変わってくる部分ではあるので、
きちんとベンチマークを取った方がよいとは思う。
DBMSのチューニングに王道は無いので。
テーブルのレコードは1対1です。
基本的には問題ないものの、用途次第ということですね。
回答どうも有り難うございました。
テーブルAとテーブルBが1対1対応なら、テーブルCとして1本化すべきです。
インデックスを張る必要がなくなる分、SQL文が簡単になりますし(よって検索速度向上も期待できる)、メンテナンス性も良くなります。
なるほど。
有り難うございます。参考にさせて頂きます。
>テーブルA単体時と同等の速度がでるものなんでしょうか
データ件数が数万件程度で、
記事本文の大きさが常識の範囲内の大きさなら、同等の速度がでます。
>テーブルをまとめることのメリットとデメリットを教えて下さい。
参照とINSERTのみなら、2つに分ける意味を見出すほうが難しいかも。
更新とかそういうのが絡んでくるなら、何らかの条件で2つに分けるメリットがあるかも。
実践的データモデリング入門 (DB magazine selection)
真野 正
通常は、正規化してテーブルを分けます。
この時点で、速度とかシステム用件に問題がなければそのままにします。
ここで問題がある場合は、一部を非正規化することを考えます。
数万件程度なら、JOINしてもそんなに遅くなりようがないとおもうけど。
>テーブルのサイズが巨大になってもインデックスのサイズがメモリ内に収まってれば大丈夫かな、
>と思ったんですがそう簡単にはいかないのでしょうか
記事本文の大きさが数KB程度なら、ぜんぜん問題にならないと思われます
まだプロトタイプで段階なので、最初は正規化してテーブルを分けるのもありですね。
参考になります。回答有り難うございます。
テーブル A の 本文 ID と テーブル B の本文 ID が 1:1 とのことなので、理論的には テーブルを2つに分ける必要はありません。 テーブル C のような構成で大丈夫です。
が、 記事本文 が非固定長でかつ長い場合等は、 そもそも 記事本文を RDBMS 上に持たずに、通常のファイルシステム上に置き、 本文 ID の代わりに、 ファイルシステムへのパス情報(もしくはファイルシステムへ到達できるID情報)を持たせることも検討された方が良いと思います。
特定の記事が集中して読まれるのか、全ての記事がまんべんなく読まれるのかで挙動が変わりますが、後者の場合 RDBMS 上のバッファのヒット率が落ちてしまうことが懸念されます。
記事本文はDBに格納しない、というのも一つの方法ですね。
レプリケーションする場合はrsyncでやればいいのかな。
回答どうも有り難うございます。
回答者 | 回答 | 受取 | ベストアンサー | 回答時間 | |
---|---|---|---|---|---|
1 | windofiuly | 62回 | 37回 | 2回 | 2010-11-25 07:21:30 |
仰るとおり、メンテが面倒なので一つにまとめたいというのもあります。
テーブルのサイズが巨大になってもインデックスのサイズがメモリ内に収まってれば大丈夫かな、と思ったんですがそう簡単にはいかないのでしょうか。
回答有り難うございます。