ここで、「Aのデータと共に、関連するBとCのデータも取得したい」という一般的な要件を考えます。多くの人が最初に思いつくのは、`JOIN`を使ったクエリでしょう。
SELECT A.A_id, A.A_attrs, B.B_attrs, C.C_attrsFROM AJOIN BON A.B_id = B.B_idJOIN CON A.C_id = C.C_idWHERE A.A_id = 'some_a_id'; --特定のAレコードを取得する場合
このクエリは、B,Cの重複が大量発生し、さらに属性のデータサイズが大きい場合は非効率になる可能性があります。
データベースは`JOIN`を行う際に、結合条件に合うレコードを探すために複数のテーブルをスキャンしたり、一時的な結合結果を作成したりするオーバーヘッドが発生します。
特に、`JOIN`するテーブルの数が増えたり、それぞれのテーブルのレコード数が多かったりすると、このオーバーヘッドは顕著になります。
また、「JOIN乱用するなら第三正規形にする必要ないんだよな」という点も重要です。
第三正規形はデータの冗長性を排除し、データの一貫性を保つための設計原則です。
しかし、その結果としてデータが複数のテーブルに分散され、結合が必要になります。
もし結合による性能劣化が許容できないレベルであれば、データの一貫性を犠牲にしてでも、冗長性を持たせる(非正規化する)方がパフォーマンス上のメリットがあるというジレンマに陥ることもあります。
しかし、それは正規化のメリット(データの一貫性、更新時の不整合防止など)を失うことにもつながります。
主張されているのは、以下のようなアプローチです。
1. まずAのデータを取得する。
2. Aのデータから得られた`B_id`と`C_id`を使って、必要に応じてBとCのデータを個別に取得する。
--ステップ1: Aのデータを取得SELECT A_id, B_id, C_id, A_attrsFROM AWHERE A_id = 'some_a_id';--アプリケーション側で、上記で取得したB_idとC_idを元に、必要であれば以下のクエリを発行--ステップ2: Bのデータを取得 (例: Aから取得したB_idが'b1', 'b2'だった場合)SELECT B_id, B_attrsFROM BWHERE B_id IN ('b1', 'b2');--ステップ3: Cのデータを取得 (例: Aから取得したC_idが'c1', 'c2'だった場合)SELECT C_id, C_attrsFROM CWHERE C_id IN ('c1', 'c2');
この方法の利点は以下の通りです。
よくさ、joinすれば簡単だからっつってjoin多用するバカいるじゃん、SQLの話ね でもさ、join乱用するなら第三正規形にする必要ないんだよな A: A_id, B_id, C_id, A_attrs B: B_id, B_attrs C: C_id, C_attrs ...
すまん、「効率いい」テーブル設計とsqlのサンプル頼むわ 日本語では主張が理解できんかった
SQLを使って説明してみましょう。 過度なJOINが非効率なケース ご提示のテーブル構造を例に説明します。 Aテーブル: `A_id` (主キー), `B_id` (外部キー), `C_id` (外部キー), `A_attrs` (Aの属性)...
すまん、「効率いい」テーブル設計とsqlのサンプル頼むわ MANKO
Aが1レコードならどっちでも大差ないが、複数レコードなら、所謂N+1問題(ぐるぐるSQL)にならん?