0

2 人のユーザー間の会話を保存するデータベースがあります。メッセージ テーブルと一緒に会話テーブルを保持します。会話テーブルには 2 人のユーザー間の会話が格納され、メッセージ テーブルには特定の会話のメッセージが格納されます。MSN メッセンジャーや Facebook メッセージなど、2 人のユーザー間の会話は 1 つだけで、新しいメッセージはこの会話に追加されます。これを行うには2つのアイデアがあります。

最初のアプローチ:

conversations(c_id, user1, user2) 

c_id は主キーです auto_incremented

messages(m_id, c_id, user_from, user_to, content) 

m_id は主キー auto_incremented、c_id は外部キー参照の会話 (c_id) です。

2番目のアプローチでは、

conversations(user1, user2) 

(user1, user2) は複合主キー

messages(m_id, user_from, user_to, content) 

m_id は主キー、(user_from, user_to) は外部キー参照の会話 (user1, user2) です。

私の質問は、これらのどれがより良いですか? 1番目、2番目、またはなし?私は自分の設計で複合外部キーをまだ使用したことがなく、正直なところ、結果がどうなるかわかりません。

これらすべてのフィールドとは別に、読み取り日、入力日などのフィールドがあります。簡潔にするために、私はそれらをスキップしています。

4

2 に答える 2

0

キー/インデックスの決定は、データのクエリ方法に大きく影響されます。クエリのパフォーマンスがはるかに重要であると仮定して、挿入のパフォーマンスを無視します(これは間違った仮定である可能性があり、あなただけがそれを知っています)。また、列名に基づいて、メッセージの方向が重要であると想定しています。同じ会話内の場合と同様に、ユーザーXがメッセージuser_from列に含まれることもあれば、user_to列に含まれることもあります。ローレンスへのコメントで、最初にユーザーが参加した会話のリストを表示し、次にユーザーが1つをクリックすると、メッセージのリストが表示されると述べました。したがって、おそらく結合を検討しているのではなく、一度に1つの会話のメッセージしか取得しないため、クエリのペアを検討しています。

クエリ1は、ユーザーXの会話の選択になります。たとえば、user1=Xまたはuser2=Xの会話から*を選択します。

この時点で、両方のオプションは同等です。ここで、2番目のクエリは特定の会話のメッセージを取得します。

オプション1:メッセージから*を選択します。ここでc_id =?(最初のクエリでc_idがフェッチされ、リストボックスの各行に関連付けられました)

オプション2:リストボックスをクリックすると、ユーザーXとYの間の会話のメッセージが必要であることがわかります。

select * from messages where(user_from = X and user_to = Y)OR(user_from = Y and user_to = X)

ここで私を導くすべての仮定が正しければ、オプション1が非常に高速な単一値の主キー検索であるため、明らかにオプション1の方が優れています。それ以外の場合は、データをクエリする方法について同様の分析を行います。これにより、より適切なソリューションが示されます。

(余談ですが、メッセージテーブルでは、2人のユーザーを繰り返す代わりに、会話テーブルにすでに順序があるため、会話の方向を示す0/1ビット列があります。たとえば、会話テーブルにcid 1がある場合、user X、ユーザーYの場合、cid 1のメッセージテーブルでは、ユーザーxがfromユーザーの場合はビットをゼロに設定し、ユーザーyがfromユーザーの場合はビットを1に設定できます)

于 2012-11-19T22:22:09.053 に答える
0

私の個人的な好みは、複合 FK を持たないことです。複合 PK を持つテーブルと別のテーブルの間に 1 対多の関係がある場合、経験則として、単一の列の主キー (自動インクリメント、連結) を作成します。既存の列または一意のキー生成の方法でそれをカットします)、それをキーにします。複合 FK は、2 つのテーブル間の関係を視覚化するには、あまりにも複雑すぎると思います。

YMMV

于 2012-11-19T22:26:39.993 に答える