Ich habe eine INNODB-Tabelle levels
:
+ -------------------- + -------------- + ------ + ----- + --------- + ------- + | Feld | Geben Sie | ein Null | Schlüssel | Standard | Extra | + -------------------- + -------------- + ------ + ----- + --------- + ------- + | id | int (9) | NEIN | PRI | NULL | | | Levelname | varchar (20) | NEIN | | NULL | | | user_id | int (10) | NEIN | | NULL | | | Benutzername | varchar (45) | NEIN | | NULL | | | Bewertung | dezimal (5,4) | NEIN | | 0,0000 | | | Stimmen | int (5) | NEIN | | 0 | | | spielt | int (5) | NEIN | | 0 | | | date_published | Datum | NEIN | MUL | NULL | | | user_comment | varchar (255) | NEIN | | NULL | | | spielbarer_Zeichen | int (2) | NEIN | | 1 | | | is_featured | tinyint (1) | NEIN | MUL | 0 | | + -------------------- + -------------- + ------ + ----- + --------- + ------- +
Es gibt ~ 4 Millionen Zeilen. Aufgrund der Front-End-Funktionalität muss ich diese Tabelle mit einer Vielzahl von Filtern und Sortierungen abfragen. Sie sind auf playable_character
, rating
, plays
, und date_published
. Sie date_published
können nach dem letzten Tag, der letzten Woche, dem letzten Monat oder jederzeit (in den letzten 3 Jahren) gefiltert werden. Es gibt auch Paging. Abhängig von den Benutzeroptionen können die Abfragen beispielsweise wie folgt aussehen:
SELECT * FROM levels
WHERE playable_character = 0 AND
date_published BETWEEN date_sub(now(), INTERVAL 3 YEAR) AND now()
ORDER BY date_published DESC
LIMIT 0, 1000;
SELECT * FROM levels
WHERE playable_character = 4 AND
date_published BETWEEN date_sub(now(), INTERVAL 1 WEEK) AND now()
ORDER BY rating DESC
LIMIT 4000, 1000;
SELECT * FROM levels
WHERE playable_character = 5 AND
date_published BETWEEN date_sub(now(), INTERVAL 1 MONTH) AND now()
ORDER BY plays DESC
LIMIT 1000, 1000;
Ich sollte das hinzufügen rating
und werde plays
immer als abgefragt DESC
. Nur date_published
kann entweder DESC
oder sein ASC
.
Ich habe mit einem Index begonnen idx_date_char(date_published, playable_character)
, der bei der ersten Beispielabfrage hier hervorragend funktioniert hat. Basierend auf einigen anderen Antworten habe ich zu zwei anderen Indizes gewechselt (date_published, playable_character, play) und (date_published, playable_character, Bewertung).
Die erste Abfrage wird immer noch sehr schnell ausgeführt. In EXPLAIN passieren jedoch einige ungewöhnliche Dinge, wenn player_character = x eine bestimmte Anzahl von Zeilen (~ 700.000) überschreitet: In EXPLAIN wird USING WHERE angezeigt.
Die erste Frage ist also, ob Verbesserungen an der Abfrage oder den Indizes möglich sind, und zweitens, welche MySQL-Einstellungen geändert werden sollten, um die großen Ergebnismengen zu berücksichtigen.
Anregungen sehr geschätzt. TIA.
Antworten:
Beginnen Sie mit dem Element "=" und führen Sie dann den Bereich aus:
"Paginierung", a la
ORDER BY rating DESC LIMIT 4000, 1000;
wird am besten gemacht, indem Sie sich daran erinnern, wo Sie "aufgehört" haben. Auf diese Weise müssen Sie nicht über die 4000 Datensätze scannen, die Sie nicht benötigen.quelle
Erstellen Sie beide Indizes für eine bessere Leistung, wenn nicht viele Einfüge- oder Aktualisierungsabfragen erforderlich sind:
Andernfalls, wenn das Einfügen und Aktualisieren von Abfragen in dieser Tabelle häufiger verwendet wird als das Erstellen eines Index:
oder erstellen Sie keinen Index
quelle
Allen hier fehlt ein Punkt - die fraglichen SQLs rufen 1000 Zeilen ab. Und 1000 Zeilen können nur dann schnell abgerufen werden, wenn die meisten Daten zwischengespeichert sind. Wenn die Daten nicht zwischengespeichert werden, müssen nacheinander 1000 zufällige Lesevorgänge durchgeführt werden, um die Daten abzurufen.
Guter festplattenbasierter Speicher mit schnellen Festplatten bietet bis zu ~ 200 Lesevorgänge pro Sekunde. Gängige Festplatten auch in RAID Ich bezweifle, dass sie sogar 100 verwalten. Das bedeutet mehr als 10 Sekunden, um selbst mit den besten Indizes Ergebnisse zu erzielen.
Auf längere Sicht funktionieren solche Datenmodelle und Abfragen also nicht. Jetzt werden die Abfragen schnell ausgeführt, wenn Sie auf zwischengespeicherte Daten klicken.
quelle