0

私はこの次の表を持っています:

Matches -> match_id, team_a_id , team_b_id, score

このテーブルは、2つのチーム(チームAとチームB)間の一致を記録します。ただし、チームAがホストとしてプレイすることもあれば、チームBがホストとしてプレイすることもあります。したがって、チームaとチームbの間で一致する履歴を見つけようとしたとき。私が現在していることは

select * from matches where (team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1);

そのような場合へのより良いアプローチはありますか?上記のクエリに関して、team_a_idとteam_b_idの組み合わせのインデックスを含めるのは正しいですか?しかし、それでも、ABORBAの間に論理OR条件があります。

あるいは、私は別のアイデアを持っています、それは別のテーブルに歴史を言わせることです

History -> team_hash, match_id

ここでteam_hashを手動で作成しhash(a,b) == hash(b,a)ます。ただし、これにより、挿入はわずかに遅くなりますが、読み取りは速くなります。それとも本当に速く読めますか?

4

2 に答える 2

0

に複合インデックスがあると仮定すると、DBMS は 2 つのインデックス シーク (1 つは 用、もう1 つは 用){team_a_id, team_b_id}のみを使用して SQL ステートメントを実行できます。これは非常に高速です。パフォーマンスが不足しているとは思わないでください。team_a_id = 1 and team_b_id = 2team_a_id = 2 and team_b_id = 1


ただし、これらのインデックス シークのいずれかを排除する方法があります。制約を追加...

CHECK(team_a_id < team_b_id)

...必要に応じて、別のフィールドに「方向」(つまり、どのチームがホストであるか) をエンコードします。このように、team_a_id = 2 and team_b_id = 1が真になることは決してないことがわかっているので、 で検索するだけで済みますteam_a_id = 1 and team_b_id = 2


「対称」ハッシュは素晴らしいアイデアですが、次のようになります。

  • ハッシュの正確性を宣言的に強制することはできません。トリガーまたはアプリケーション レベルで行う必要があります。
  • 冗長データです。team_a_idハッシュの競合を解決するには、team_b_idとにかく維持する必要があります。データが大きいということは、事実上、キャッシュが小さいことを意味します。
  • 実際にはインデックスの数が増える可能性があります。参照整合性を効率的に実施するには、実際の SQL クエリにインデックスが必要ない場合でも、おそらくインデックスが必要にteam_a_idなります。team_b_idキャッシュへの負担が増えるだけでなく、追加のすべてのインデックスを維持する必要があるため、INSERT/UPDATE/DELETE のパフォーマンスが低下する可能性があります。クラスタリングをオフにできない InooDB では状況が特に深刻であるため、セカンダリ インデックスはヒープベースのテーブルよりも高価になる傾向があります (この記事の「クラスタリングの欠点」を参照してください)。
于 2012-07-29T20:18:08.643 に答える
0

WHERE 句を次のようにすることもできます

((team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1))
AND team_a_id IN (1,2) AND team_b_id IN (1,2)

これにより、(team_a_id,team_b_id) のようなインデックスを使用できるようになります。

于 2012-07-29T21:28:49.287 に答える