私は約20000行の "match_players"という名前の関係テーブルを持っています。 「hero_id」という名前の列があり、これはマッチで選手が選んだ英雄を表しています。すべてのフィールドが索引付けされます。痛いほど遅い自己JOIN
私は私の現在のクエリを約かかり など、彼らは敵だった何回、彼らは同じチームにいた回数をカウントし、2人の英雄のすべての組み合わせからなる別のテーブルを構築する必要があります8コアSSDサーバーで90秒。私はそれが結果をグループ化する前に内部的にすべての組み合わせのこの大規模なテーブルを構築するMySQLと関係があると思います。
行の値の組み合わせを収集する別の方法があります.MySQLが単にテーブルをスキャンし、見つかったときに新しい組み合わせを記録しているのでしょうか?すべての入力をいただければ幸いです。
表 "match_players":
match_id | team | position | player_id | hero_id |
56427859 | 1 | 1 | 546107 | 17 |
56427859 | 1 | 2 | 469333 | 81 |
56427859 | 1 | 3 | 227526 | 60 |
56427859 | 1 | 4 | 193739 | 32 |
56427860 | 0 | 0 | 473923 | 11 |
56427860 | 0 | 1 | 292764 | 93 |
56427860 | 0 | 2 | 138018 | 26 |
56427860 | 0 | 3 | 326510 | 96 |
etc...
クエリ:
SELECT mp1.hero_id, mp2.hero_id
FROM match_players mp1
INNER JOIN match_players mp2
ON mp1.hero_id < mp2.hero_id
WHERE mp1.team = mp2.team
GROUP BY mp1.hero_id, mp2.hero_id
説明します
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
1 | SIMPLE | mp1 | ALL | faction_id,hero_id | NULL | NULL | NULL | 34060 | Using temporary; Using filesort
1 | SIMPLE | mp2 | ref | faction_id,hero_id | faction_id | 1 | beta_dota_2.mp1.faction_id | 3499 | Using where
更新:
私はマッチにあったヒーローのみが必要なので、私は次のようにクエリを更新しました。それははるかに高速です。私はそれが数10分の1秒で完了すると思います。
SELECT mp1.hero_id, mp2.hero_id
FROM match_players mp1
INNER JOIN match_players mp2
ON mp1.hero_id < mp2.hero_id
WHERE mp1.team = mp2.team AND mp1.match_id = mp2.match_id
GROUP BY mp1.hero_id, mp2.hero_id
私はすべての英雄の組み合わせのリストを望んでいた場合、私はまだそれについて移動する最良の方法はどのようになるか、同じ試合であるか否か、しかし、知っていただきたいと思いますか?明らかに、数千行を超えるテーブルの元のクエリでは実現不可能です。このクエリの
「痛みを伴う」とは、通常、「テーブルをインデックス登録するのを忘れた」ことを意味します。 'EXPLAIN'とは何ですか? '<'節は通常問題になりますが、直接のマッチは速くなります。あなたが実際に壁にぶつかっているなら、多分これをスクリプト言語でメモリにロードし、それをそのように処理してください。 – tadman
@tadman - 私は自分の投稿にEXPLAINを追加しました。 – DaiBu