2009-04-17 4 views
4

J'ai un jeu en ligne où j'écris beaucoup de statistiques de jeu. Ces tables de statistiques deviennent très rapidement très volumineuses, et je dois faire attention car il suffit d'enregistrer plus de statistiques pour que les performances du jeu soient assez mauvaises, une fois que la table sera suffisamment grande. Ma stratégie, qui n'est pas très bonne, est de garder les tables de statistiques petites. J'ai un processus automatique qui crée une nouvelle table toutes les 24 heures, empêchant la performance d'être trop incontrôlable. Mais ma solution est moche et est une sorte de "rotation" des tables de statistiques. J'utilise innodb et j'ai mis en place quelques index pour améliorer les performances, et puis je garde juste 30 de ces tables (chacune étant de 24 heures, donc j'enregistre un mois de stats). Toutes les 24 heures, mon processus automatisé supprime la table "stats30", puis renomme toutes les tables numérotées pour en avoir un plus grand nombre, puis crée une nouvelle table vierge appelée simplement "stats". C'est la table "live", où les statistiques sont activement enregistrées.MySQL idée de "rotation" de gros volume de statistiques?

Ces tables enregistrent fondamentalement chaque transaction entre chaque joueur et chaque autre joueur dans le jeu avec lequel elles interagissent, donc une explosion exponentielle des données. Lorsqu'une nouvelle transaction se produit, elle vérifie s'il existe déjà une ligne pour les transactions entre ces deux joueurs au cours de cette journée. Si c'est le cas, il met à jour la ligne avec les modifications apportées à leurs transactions. Sinon, il crée une nouvelle ligne. Une paire de joueurs qui interagissent 1000 fois dans une journée et une paire qui interagissent une seule fois n'auront qu'une seule rangée dans la table pour ce jour. Chaque action sur la base de données implique un SELECT puis un UPDATE ou un INSERT, de sorte qu'il est assez même entre les lectures et les écritures telles qu'elles sont actuellement conçues. La lecture de données dans un sens plus large, c'est-à-dire pour l'analyse de statistiques et de joueurs multiples, est faite très rarement, par rapport aux SELECT, UPDATEs et INSERTs uniques. Il y a environ 150 000 lignes créées par jour.

Je sais que cela pourrait être mieux. Je ne peux pas facilement réduire la quantité de données que j'enregistre, mais je suis préoccupé par 1.performance, et 2.simplicity. Je pourrais encore augmenter les performances en créant une nouvelle table toutes les 4 heures, par exemple, mais je devrais jouer avec 180 tables. Inversement, je pourrais le rendre plus simple en n'utilisant qu'une seule table, et tout s'arrêterait. Notez que j'ai besoin de mettre à jour des lignes dans ces tables, donc je ne peux pas utiliser quelque chose comme le moteur de stockage ARCHIVE, mais j'ai seulement besoin de INSERT ou UPDATE sur la table de statistiques "live".

Il y a aussi le problème mineur que lorsque le processus de rotation quotidienne se produit, toutes les requêtes arrivant à ce moment peuvent être perdues. (S'il est en train de renommer toutes les tables et en créer une nouvelle, les nouvelles entrées peuvent échouer.) Perdre quelques insertions n'est pas un gros problème, mais une solution où cette erreur ne se produira pas ou pourrait être faite "atomiquement". " serait mieux.

Merci pour toutes les idées qui pourraient aider! :)

+1

Combien de rangs avez-vous par jour? Sont-ils lus une fois lus plusieurs fois? Par exemple, une fois que vous écrivez une ligne dans la base de données, est-ce qu'elle est mise à jour? – idrosid

+0

Je suis assez sceptique que la performance de MySQL est le vrai goulot d'étranglement ici. – Pesto

+0

On dirait que vous créez un énorme gâchis. Vous devriez totalement laisser tomber cela et utiliser JQUERY! – belgariontheking

Répondre

0

Aucun gourou de la base de données, mais avez-vous essayé d'utiliser un autre moteur de base de données (innoDB est lent, essayez myISAM) et assurez-vous que les données que vous sélectionnez sont indexées?

semble une question stupide mais, cette solution vous est assez fou

aussi essayer ceci: http://forums.mysql.com/read.php?24,92131,92131 pour l'optimisation des performances.

+0

Depuis qu'il a choisi InnoDB, je suppose qu'il cherche à obtenir la conformité ACID qui l'accompagne. –

+0

J'ai ajouté un autre paragraphe pour mieux expliquer le problème. J'ai vraiment besoin de quelque chose avec un verrouillage au niveau des lignes. – DivideByHero

0

La première chose à faire est de profiler votre application pour trouver ce qui prend le plus de temps. Il ne sert à rien de continuer avec cette rotation de table si un autre changement donne de meilleures performances.

Exécutez EXPLAIN sur toutes vos requêtes et assurez-vous de bien comprendre les résultats et optimize your queries appropriately.Je recommande également fortement de lire le Reference Manual for optimizing MySQL. Il donne de nombreux conseils sur la façon de configurer le serveur pour des performances optimales et peut vous donner des informations sur ce qui peut provoquer des goulots d'étranglement au niveau des performances. Si la performance de la table dynamique est réellement le problème et que vous devez réduire le nombre de lignes dans cette table, déplacez simplement les lignes dans une table d'archivage. De cette façon, vous avez toujours une table en direct mince. et peut facilement exécuter des requêtes plus longues sur l'archive.

0

De combien de lignes parlons-nous ici? Des millions? Des centaines de milliers? Puisque vous avez dit que vous avez seulement besoin de mettre à jour les lignes dans la table en direct, il semble que vous pourriez probablement le faire avec seulement deux tables - une table de statistiques en direct et une table d'archives de statistiques. Votre travail par lots déplacerait alors simplement les lignes de la table de statistiques en direct dans la table stats_archive périodiquement. Un autre travail peut nettoyer les lignes de la table d'archivage après un certain âge. Ce serait également une bonne idée d'avoir un troisième travail qui recalcule périodiquement les statistiques sur la table d'archivage pour s'assurer que MySQL peut générer de bons plans pour vos requêtes.

+0

Bonne idée! J'ai ajouté plus d'informations de fond à la publication. C'est dans les centaines de milliers par jour. Je peux essayer une approche à deux tables ... – DivideByHero

0

Je voudrais en savoir plus sur votre domaine pour donner une réponse plus précise. Mais une réponse courte, vous auriez besoin d'une sorte de partitionnement basé sur le mois, l'année ou géographique. Ainsi, toutes les statistiques des utilisateurs appartenant à une ville particulière iront dans ces tableaux. De cette manière, vos sélections peuvent devenir plus rapides.

Et bien sûr, le blabla habituel sur l'ajout d'index ...

Dites-moi plus, je pourrais peut-être vous aider ...

2

Avec 150k lignes par jour, quel est le moyen. taille d'une rangée? Ces lignes contiennent-elles des données redondantes que vous pourriez peut-être minimiser en ne conservant que les références?

En général, c'est toujours une bonne chose de garder les tables petites afin que les mises à jour d'index passent rapidement. Aussi, comme mentionné par Ben S ci-dessus vos requêtes devraient être optimisées au moins afin qu'il n'y ait aucun accès aux colonnes avec l'index manquant, etc. Vous pouvez trouver quelques problèmes possibles utilisant EXPLAIN et dans le journal lent de requête de votre serveur mysql si vous avez l'ai activé.

Une chose qui pourrait vous aider avec les problèmes de performance est le démon memcached. En l'utilisant, vous pouvez retarder les écritures sur votre DB, en supprimant ainsi une partie de la vapeur et ne souffrez pas de caches sales et similaires. Bien que cela dépende du framework d'application que vous utilisez (le cas échéant), cela nécessite un certain travail pour l'implémenter dans votre application.

Pour des raisons d'archivage et de statistiques, je vous suggère de consulter InfoBright (http://www.infobright.org/). C'est une version open source de MySQL en remplacement (basée sur MySQL). Son but désigné est d'être un magasin d'entrepôt de données. Vous pouvez l'utiliser pour toutes sortes d'analyses de données à haut volume. Il possède une très bonne fonction de compression, qui dans notre cas réduit ~ 23 To de données brutes à environ 1,2 To de données compressées. Je suppose qu'il est inutile de dire que l'interrogation de lignes spécifiques de données compressées peut/sera assez lente. Mais pour les statistiques, c'est sacrément rapide. Donc, si vous n'interrogez pas des lignes spécifiques mais que vous analysez plutôt des choses comme "combien de lignes ont été mises à jour avec la valeur foo> bar entre le 08 et le 09", cela vous donnera de très bonnes performances. En fait, lorsque vous utiliserez la base de données, elle analysera votre utilisation et créera une grille de connaissances qui optimisera ses données pour vos requêtes spécifiques. La question suivante qui me vient à l'esprit est la suivante ... si ce sont «seulement» les statistiques/données de session que vous gardez pendant une journée, ou quelques heures, est-ce qu'un DB relationnel est le bon outil pour le travail? Sans connaître la nature exacte de votre application, je pourrais imaginer une sorte de sessions en mémoire (qui pourraient résider dans un cluster en terre cuite, par exemple) qui écrivent un journal de transactions et commettent leurs données de temps en temps. Mais comme je l'ai dit, cela dépend beaucoup de la nature de votre application et du nombre de données en question.

Questions connexes