2009-04-17 2 views
4

Ich habe ein Online-Spiel, in dem ich viele Gameplay-Statistiken aufzeichne. Diese Statistiktabellen werden sehr schnell groß, und ich muss vorsichtig sein, da das Aufzeichnen von mehr Statistiken dazu führen kann, dass die Leistung des Spiels ziemlich schlecht wird, sobald der Tisch groß genug ist.MySQL-Idee für High-Volume "Rotation" von Statistiken?

Meine Strategie, die nicht sehr gut ist, besteht darin, die Statistiktabellen klein zu halten. Ich habe einen automatischen Prozess, der alle 24 Stunden eine neue Tabelle erstellt, sodass die Leistung nicht zu sehr aus der Hand geht. Aber meine Lösung ist hässlich und ist eine Art "Rotation" von Statistiktabellen. Ich benutze innodb und habe ein paar Indizes eingerichtet, um die Leistung zu verbessern, und dann behalte ich nur 30 dieser Tabellen herum (jeder ist 24 Stunden, also spare ich einen Monat Statistik). Alle 24 Stunden löscht mein automatisierter Prozess die Tabelle "stats30", benennt dann alle nummerierten Tabellen in eine höhere Nummer um und erstellt dann eine neue, leere Tabelle namens "stats". Dies ist die "Live" -Tabelle, in der die Statistiken aktiv aufgezeichnet werden.

Diese Tabellen zeichnen im Grunde jede Transaktion zwischen jedem Spieler und jedem anderen Spieler im Spiel auf, mit dem sie interagieren, also eine exponentielle Datenexplosion. Wenn eine neue Transaktion auftritt, überprüft sie, ob es bereits eine Zeile für die Transaktionen zwischen diesen beiden Spielern während dieses Tages gibt. Wenn dies der Fall ist, aktualisiert es die Zeile mit Änderungen an ihren Transaktionen. Andernfalls wird eine neue Zeile erstellt. Ein Paar Spieler, die an einem Tag 1000-mal interagieren, und ein Paar, die nur einmal interagieren, haben für diesen Tag jeweils nur eine Zeile in der Tabelle. Jede Aktion in der Datenbank beinhaltet ein SELECT und dann entweder ein UPDATE oder ein INSERT, so dass es ziemlich genau zwischen Lese- und Schreibvorgängen wie aktuell entworfen ist. Das Lesen von Daten in einem größeren Sinn, d. H. Für die Analyse von Statistiken und mehreren Spielern, wird sehr selten im Vergleich zu den einzelnen SELECTs, UPDATEs und INSERTs durchgeführt. Es werden ungefähr 150.000 Zeilen pro Tag erstellt.

Ich weiß, das könnte besser sein. Ich kann die Menge der Daten, die ich aufnehme, nicht so leicht reduzieren, aber ich mache mir Gedanken über die 1. Leistung und 2. Einfachheit. Ich könnte die Leistung sogar noch steigern, indem ich zum Beispiel alle 4 Stunden einen neuen Tisch kreiere, aber dann muss ich mich mit 180 Tischen messen. Umgekehrt könnte ich es einfacher machen, indem ich nur einen Tisch benutze, und dann hört alles krachend auf.

Beachten Sie, dass ich Zeilen in diesen Tabellen aktualisieren muss, so dass ich nicht so etwas wie die ARCHIVE-Speicher-Engine verwenden kann, aber ich muss nur auf die "Live" Statistik-Tabelle INSERT oder UPDATE.

Es gibt auch das kleinere Problem, dass wenn der tägliche Rotationsprozess auftritt, alle Anfragen, die zu diesem Zeitpunkt eingehen, verloren gehen können. (Wenn Sie alle Tabellen umbenennen und eine neue erstellen, können neue Einträge fehlschlagen.) Das Verlieren einiger Einfügungen ist kein großes Problem, sondern eine Lösung, bei der dieser Fehler nicht auftritt oder "atomisch" ausgeführt werden kann " wäre besser.

Danke für alle Ideen, die helfen könnten! :)

+1

Wie viele Zeilen haben Sie pro Tag? Sind sie einmal gelesen - viele Male? Dh, sobald Sie eine Zeile in der DB schreiben, wird sie jemals aktualisiert? – idrosid

+0

Ich bin ziemlich skeptisch, dass die Leistung von MySQL hier der eigentliche Flaschenhals ist. – Pesto

+0

Es sieht so aus, als ob du ein riesiges Durcheinander verursachst. Sie sollten das vollständig fallen lassen und JQUERY verwenden! – belgariontheking

Antwort

0

Kein Datenbank-Guru, aber haben Sie versucht, eine andere db-Engine (innoDB ist langsam, versuchen myISAM) und sicherzustellen, dass die Daten, die Sie auswählen, indiziert ist?

scheint wie eine dumme Frage, aber diese Lösung Sie haben, ist ziemlich verrückt

auch diese versuchen: http://forums.mysql.com/read.php?24,92131,92131 für Performance-Tuning.

+0

Da er sich für InnoDB entschieden hat, nehme ich an, dass er die ACID-Konformität sucht, die damit einhergeht. –

+0

Ich habe einen weiteren Absatz hinzugefügt, der das Problem besser erklärt. Ich brauche auf jeden Fall etwas mit Sperren auf Zeilenebene. – DivideByHero

0

Das erste, was zu tun ist, profilieren Sie Ihre Anwendung, um herauszufinden, was tatsächlich die meiste Zeit kostet. Es macht keinen Sinn, mit dieser Tabellenrotation fortzufahren, wenn eine andere Änderung eine bessere Leistung ergibt.

Führen Sie EXPLAIN auf alle Ihre Abfragen und stellen Sie sicher, dass Sie die Ergebnisse verstehen und optimize your queries appropriately.

Ich empfehle auch dringend, lesen Sie die Reference Manual for optimizing MySQL. Es enthält viele Tipps zur Konfiguration des Servers für optimale Leistung und gibt Ihnen möglicherweise einen Überblick darüber, was zu Leistungsengpässen führen könnte.

Wenn die Leistung der Live-Tabelle wirklich das Problem ist und Sie die Anzahl der Zeilen in dieser Tabelle reduzieren müssen, verschieben Sie die Zeilen einfach in eine Archivtabelle. Auf diese Weise haben Sie immer einen schlanken Live-Tisch. und können problemlos länger laufende Abfragen im Archiv ausführen.

0

Wie viele Zeilen reden wir hier? Millionen? Hunderttausende?

Da Sie gesagt haben, dass Sie nur Zeilen in der Live-Tabelle aktualisieren müssen, klingt es, als könnten Sie dies wahrscheinlich mit nur zwei Tabellen tun - einer Live-Statistik-Tabelle und einer Statistik-Tabelle. Ihr Stapeljob würde dann in regelmäßigen Abständen Zeilen aus der Tabelle "Live-Statistiken" in die Tabelle "stats_archive" verschieben. Ein anderer Job könnte Zeilen aus der Archivtabelle löschen, nachdem sie ein bestimmtes Alter erreicht haben. Es wäre auch eine gute Idee, einen dritten Job zu haben, der regelmäßig Statistiken über die Archivtabelle berechnet, um sicherzustellen, dass MySQL gute Pläne für Ihre Abfragen generieren kann.

+0

Gute Idee! Ich habe dem Beitrag weitere Hintergrundinformationen hinzugefügt. Es ist in den Hunderttausenden pro Tag. Ich kann einen Dual-Table-Ansatz versuchen ... – DivideByHero

0

Ich möchte mehr über Ihre Domain wissen, um eine genauere Antwort zu geben. Aber kurze Antwort, Sie benötigen eine Art von Partitionierung entweder basierend auf Monat, Jahr oder geografisch. Daher werden alle Statistiken von Benutzern, die zu einer bestimmten Stadt gehören, in diese Tabellen aufgenommen. Auf diese Weise können Ihre Auswahlen schneller werden.

Und natürlich das übliche Blabla über das Hinzufügen von Indizes ...

Sag mir mehr, ich in der Lage sein, Ihnen ...

2

Mit 150k Zeilen pro Tag zu helfen, was die avg ist. Größe einer Reihe? Sind in diesen Zeilen redundante Daten enthalten, die möglicherweise minimiert werden können, indem Referenzen beibehalten werden?

Im Allgemeinen ist es immer eine gute Sache, Tabellen klein zu halten, damit Index-Updates schnell durchgehen. Wie von Ben S oben erwähnt, sollten Ihre Abfragen mindestens so optimiert sein, dass es keinen Zugriff auf Spalten mit fehlendem Index usw. gibt. Sie können einige mögliche Probleme mit EXPLAIN und im langsamen Abfrageprotokoll Ihres mysql-Servers finden habe es aktiviert.

Eine Sache, die Ihnen bei Leistungsproblemen helfen kann, ist der Memcached-Daemon. Mit ihr können Sie Schreibvorgänge in Ihre DB verzögern und dadurch etwas Dampf wegnehmen und trotzdem nicht unter schmutzigen Caches und dergleichen leiden. Abhängig vom verwendeten Anwendungsframework (falls überhaupt) benötigt es einige Arbeit, um dies in Ihre Anwendung zu implementieren.

Für Archivierungs- und Statistikzwecke empfehle ich einen Blick auf InfoBright (http://www.infobright.org/). Es ist ein Open-Source-MySQL-Ersatz (basierend auf MySQL). Es ist ein Zweck, ein Data Warehouse Store zu sein. Sie können es jedoch für alle Arten von Datenanalyse mit hohem Volumen verwenden. Es hat eine sehr schöne Komprimierungsfunktion, die in unserem Fall ~ 23 TB Rohdaten auf etwa 1,2 TB komprimierte Daten reduziert. Ich denke, es ist unnötig zu sagen, dass die Abfrage bestimmter Zeilen komprimierter Daten sehr langsam ist. Aber für Statistiken ist es verdammt schnell. Wenn Sie also keine bestimmten Zeilen abfragen, sondern Dinge wie "Wie viele Zeilen wurden zwischen dem 08. und dem 09. Februar mit dem Wert foo> bar aktualisiert" werden, erhalten Sie eine sehr gute Leistung. Wenn Sie die DB verwenden, analysiert sie Ihre Verwendung und erstellt ein Wissensraster, das die Daten für Ihre spezifischen Abfragen optimiert. Die nächste Frage, die mir in den Sinn kommt, ist ... wenn es "nur" Statistiken/Sitzungsdaten gibt, die Sie für einen Tag oder einige Stunden aufbewahren, ist eine relationale DB das richtige Werkzeug für den Job? Ohne die genaue Art Ihrer Anwendung zu kennen, könnte ich mir eine Art In-Memory-Sitzungen vorstellen (die zum Beispiel in einem Terrakotta-Cluster residieren könnten), die ein Transaktionslog schreiben und ihre Daten festschreiben. Aber wie gesagt, das hängt stark von der Art Ihrer Anwendung und dem Umfang der fraglichen Daten ab.