これら 2 つのアプローチがデータベースで物理的にどのように表現されるかを次に示します。

両方のアプローチを分析しましょう...
アプローチ 1 (両方向がテーブルに格納されている):
- PRO: よりシンプルなクエリ。
- CON:一方向のみの挿入/更新/削除によってデータが破損する可能性があります。
- MINOR PRO: 友情を複製できないようにするための追加の制約は必要ありません。
- さらなる分析が必要です:
- TIE: 1 つのインデックスで両方向がカバーされるため、セカンダリ インデックスは必要ありません。
- TIE: ストレージ要件。
- TIE: パフォーマンス。
アプローチ 2 (テーブルに格納されている方向は 1 つだけ):
- CON: より複雑なクエリ。
- PRO: 反対方向がないため、反対方向の処理を忘れてデータが破損することはありません。
- MINOR CON: が必要
CHECK(UID < FriendID)
なので、同じ友情が 2 つの異なる方法で表されることは決してなく、キーオン(UID, FriendID)
がその仕事を行うことができます。
- さらなる分析が必要です:
- TIE:クエリの両方向をカバー
{UID, FriendID}
するには、2 つのインデックスが必要です ( の複合インデックスと の複合インデックス{FriendID, UID}
)。
- TIE: ストレージ要件。
- TIE: パフォーマンス。
ポイント1は特に興味深いものです。MySQL/InnoDBは常にデータを クラスター化し、クラスター化されたテーブルではセカンダリ インデックスのコストが高くなる可能性があるため (この記事の「クラスタリングの欠点」を参照)、アプローチ 2 のセカンダリ インデックスが少ない行数の利点をすべて食い尽くしてしまうように見えるかもしれません。 . でも、セカンダリ インデックスにはプライマリとまったく同じフィールドが含まれているため (逆の順序でのみ)、この特定のケースではストレージのオーバーヘッドはありません。また、(テーブル ヒープがないため) テーブル ヒープへのポインターも存在しないため、通常のヒープ ベースのインデックスよりもストレージの面でさらに安価です。また、クエリがインデックスでカバーされていると仮定すると、クラスター化されたテーブルのセカンダリ インデックスに通常関連付けられているダブル ルックアップも発生しません。したがって、これは基本的に引き分けです (アプローチ 1 もアプローチ 2 も大きな利点はありません)。
ポイント 2はポイント 1 に関連しています。N 値の B ツリーを使用するか、それぞれが N/2 値を持つ 2 つの B ツリーを使用するかは問題ではありません。したがって、これも引き分けです。どちらのアプローチも、ほぼ同じ量のストレージを消費します。
同じ理由がポイント 3にも当てはまります。1 つの大きな B ツリーを検索しても、2 つの小さな B ツリーを検索しても、大きな違いはないため、これも引き分けです。
したがって、堅牢性のために、やや醜いクエリと追加の必要性にもかかわらずCHECK
、アプローチ2を使用します.