2

3 つのテーブルを持つ 1 つのデータベース:ユーザー-写真-投票
- ユーザーは多くの写真を持つことができます。
- 写真には多くの票を入れることができます。
- ユーザーは多くの写真に投票できます。
- 投票記録:
. int (-1/嫌い、0/中立、1/好き) としての結果
。投票したユーザーのID。

これが私が持っているものです(すべてのFKは削除および更新時にカスケードされます):http://grab.by/iZYE

sid =サロゲートID)

私の質問は次のとおりです。これは正しくないようです。私はこれをすでに 2 日間見ており、自信を持って先に進むことができません。これを最適化するにはどうすればよいですか、それとも完全に間違っていますか?

4

2 に答える 2

1

私が最初に目にするのは、テーブルに重複する一意のIDがあることです。sid列は必要ありません。user_id、、、photo_idおよびを使用するだけですphoto_user_id(おそらくこれをに名前変更しvote_idます)。これらのID列もINTタイプである必要があり、絶対にVARCHARsではありません。photoおそらく、 ;の投票総数の列は必要ありません。クエリを実行するだけで、必要なときに合計を取得でき、両方のテーブルの同期を維持する必要はありません。

各写真でユーザーごとに1票のみを許可すると仮定すると、の構造を変更して、列が、、、およびのみになるようにすることがuser_idできphoto_idますvote_resultuser_id次に、主キーを( 、 )の複合インデックスにしphoto_idます。ただし、外部キーを使用しているため、このテーブルは少し複雑になります。

于 2013-01-14T17:01:31.097 に答える
1

MySQL/InnoDB テーブルは常にクラスター化されます (クラスター化の詳細については、こちらこちらを参照してください)。

主キーはクラスタリング キー1としても機能するため、サロゲート主キーを使用すると、クライアント アプリケーションにとって有用な意味を持たず、クエリに使用できない順序でテーブルを物理的に並べ替えることになります。

さらに、クラスタ化されたテーブルのセカンダリ インデックスは、ヒープ ベースのテーブルよりも「太く」なる可能性があり、二重のルックアップが必要になる場合があります。

これらの理由から、次のようなサロゲートを避け、より「自然な」キーを使用する必要があります。

ここに画像の説明を入力

({USER_ID, PICTURE_NO}の tableVOTEは、 の同じ名前のフィールドを参照しますPICTUREVOTE.VOTER_ID参照。可能であれば、およびフィールドUSER.USER_IDに整数を使用してください。)*_ID*_NO

この物理モデルにより、次の非常に効率的なクエリが可能になります。

  • PICTURE特定のユーザーの写真 (プライマリ/クラスタリング インデックスの単純な範囲スキャン)。
  • 指定された画像に投票します (VOTEプライマリ/クラスタリング インデックスの単純な範囲スキャン)。状況によっては、これは実際には十分に高速な場合があるため、合計を にキャッシュする必要はありませんPICTURE

特定のユーザーの投票が必要な場合は、VOTEPK を次のように変更します{VOTER_ID, USER_ID, PICTURE_NO}。両方 (写真の投票とユーザーの投票) が必要な場合は、既存の PK を保持しますが、カバーインデックスを作成し{VOTER_ID, USER_ID, PICTURE_NO, VOTE_VALUE}ます。


1 InnoDB で。クラスタリング キーがプライマリと異なる可能性がある DBMS (MS SQL Server など) があります。

于 2013-01-14T18:34:10.850 に答える