Ich habe eine Beziehungstabelle namens "match_players", die etwa 20000 Zeilen hat. Es gibt eine Spalte namens "hero_id", die darstellt, welcher Held von einem Spieler in einem Spiel gewählt wurde. Alle Felder sind indiziert.schmerzhaft langsam selbst JOIN
Ich brauche einen anderen Tisch bauen aller Kombinationen von zwei Helden aus, mit einem zu zählen, wie oft sie auf dem gleichen Team waren, wie oft sie waren Feinde usw.
Meine aktuelle Abfrage über nimmt 90 Sekunden auf einem 8-Core-SSD-Server. Ich stelle mir vor, dass es etwas damit zu tun hat, dass MySQL diese massive Tabelle aller Kombinationen intern erstellt, bevor die Ergebnisse gruppiert werden.
Gibt es eine alternative Methode zum Sammeln von Kombinationen von Zeilenwerten, bei denen MySQL einfach die Tabelle scannt und neue Kombinationen aufzeichnet, sobald sie gefunden werden? Jede Eingabe wird geschätzt.
Table "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...
Die Abfrage:
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
ERKLÄREN:
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
Update:
Da ich nur Helden brauche, die in einem Match zusammen waren, habe ich meine Abfrage auf die folgenden aktualisiert und es ist viel, viel schneller. Ich denke, es ist in ein paar Zehntelsekunden abgeschlossen.
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
Ich würde noch gerne wissen, aber, wenn ich eine Liste von Kombinationen aller Helden wollte, ob im selben Spiel oder nicht, was der beste Weg, um darüber zu gehen wäre? Es ist eindeutig nicht machbar mit meiner ursprünglichen Abfrage auf einer Tabelle größer als ein paar tausend Zeilen.
"Schmerzhaft zeigen" bedeutet normalerweise "Ich habe vergessen, die Tabelle zu indizieren". Was sagt EXPLAIN? Eine '<' -Klausel ist normalerweise ein Problem, direkte Übereinstimmungen sind schneller.Wenn Sie wirklich gegen die Wand sind, laden Sie vielleicht alles in einer Skriptsprache in den Speicher und verarbeiten Sie es so. – tadman
@tadman - Ich habe die EXPLAIN zu meinem Beitrag hinzugefügt. – DaiBu