質問: お世話になります。 簡単なECサイトを構築しているのですが、複数階層のカテゴリを実現する方法がわからず、アドバイスいただきたいです。 DB:MySQL カテゴリA カテゴリB カテゴリC カテゴリD カテゴリE カテゴリテーブル カテゴリID カテゴリ名 親カテゴリID 1 カテゴリA 0 2 カテゴリB 1 3 カテゴリC 2 4 カテゴリD 0 5 カテゴリE 0 例えば、上記カテゴリに対しそれぞれ商品が紐付けられます。 カテゴリCを開いた際に、パンくずリストにはカテゴリAとカテゴリBを取得しておく必要がありますが、 どのように最上位階層であるカテゴリAを取得するか悩んでいます。 WEBサイトを見ていると、DBの木構造を理解しないとダメ、再帰的にSQLを発行するのはパフォーマンス的にNGなどの記述がありましたが、こういった部分の話を理解し使うようになるためには、具体的にどういった知識が必要となりますでしょうか。 データベース系の書籍を読むのが良いのか、PHP系の書籍を読むのがいいのか、 オススメの書籍、知っておくべきキーワードなどご教示いただけると大変助かります。 誠に恐れ入りますが、ご回答いただけますと幸いです。 よろしくお願いいたします。
回答: とても奥深く重要なテーマですね。自分は専門外の分野ですが、ご参考になればと思い回答します。 まず、木構造の**扱い方**と**パフォーマンスの問題**は分けて考えた方が良いです。 ### 1. 木構造の扱い方について `DB 木構造` という簡単なキーワードでググっただけでも、下記のようなとても優れた解説ページを発見することができました。 取り敢えず、下記ページをじっくり読み込んでみてはいかがでしょうか? SQLで木と階層構造のデータを扱う(1) SQLで木と階層構造のデータを扱う(2) SQLで木と階層構造のデータを扱う(3) ← gihyo.jpのSQLアタマアカデミーへのリンクになっています ⇒ 書籍なら、同著者の「達人に学ぶDB設計 徹底指南書」がおすすめです。 また、各モデルの比較は下記がよくまとまっています。 2章 Naive Trees(素朴な木) ### 2. 木構造探索のパフォーマンスについて 確かに「再帰的にSQLを発行するのはパフォーマンス的にNG」は正しいですが、パフォーマンスの問題は常に、「**データ量や階層の深さ**」vs「**実装やメンテナンスのしやすさ**」vs「**検索速度**」など相対する複数の要素間での**トレードオフ**の問題です。 いまゲストユーザーさんが構築中のECサイトで扱う予定の「複数階層のカテゴリ」は、どの程度の**規模・複雑度**でしょうか? **規模・複雑度**や**更新頻度**がそれ程でもないのであれば、適切なSQLを書く限りDBアクセスが大きなボトルネックにはならないと思いますので、実装のしやすさやメンテナンス性を重視すれば良い(言い換えると必要なら再帰的にSQLを使用しても良い)と考えます。 しかし、もしもパフォーマンスが問題になりRDBでは対応が困難(=SQLのチューニングだけでは無理)なのであれば、インメモリデータベース、分散Key-Valueストア、LDAPなどの、いわゆるNoSQLの利用を検討することもできます。 一方、従来とは全く異なるアプローチ(実際には歴史が古いが)として、ユニケージ開発手法というのも有ります。 きわめてザックリ説明すると、全てのデータを**テキストベース**で管理し、シェルスクリプトの特性を最大限に活用してシンプル、高パフォーマンスかつメンテナンス性の高いシステムを短期間に構築するという手法です。 正しく実装すると、億単位のレコード数のデータに対してもほぼ瞬時に検索可能です。 その理念を部分的に取り込むならば、 * 階層カテゴリの情報は従来通りRDBで管理する * パンくずリストに相当する階層データはテキストベースで保持する(仮に階層リストと呼ぶ) * 階層リストはカテゴリに追加・変更のあった時のみ更新する(メンテナンス時はリアルタイム性を重視しない) * 通常のページ移動時には階層リストを検索することでパンくずリストを生成する ⇒ イメージとしては、現在のページ名で階層リストをgrep→ヒットした行がそのままパンくずリスト のような仕組みにすると、相当複雑・大規模な階層カテゴリでも、速度とメンテナンス性を両立させることが可能だと思います。 結論としては、扱う予定の「階層カテゴリ」の「**規模・複雑度**」や「**更新頻度**」に応じて、パフォーマンス要件を満たす範囲でなるべくシンプルな実装にした方が良いということです。