Je construis, fondamentalement, un serveur publicitaire. C'est un projet personnel que j'essaie d'impressionner mon patron, et j'adorerais toute forme de retour sur mon design. J'ai déjà implémenté la plupart de ce que je décris ci-dessous, mais il n'est jamais trop tard pour refactoriser :)Considérations sur les très grandes tables SQL?
Ceci est un service qui fournit des bannières publicitaires (http://myserver.com/banner.jpg liens vers http://myserver.com/clicked) et fournit des rapports sur des sous-ensembles de données.
Pour chaque impression d'annonce générée et chaque clic, je dois enregistrer une ligne qui a (ID, valeur) [où la valeur est la valeur monétaire de cette transaction; par exemple. - $ .001 par bannière publicitaire diffusée à un CPM de 1 $, ou +25 $ pour un clic); ma sortie est basée sur les gains par impression [abrégé EPC]: (SUM(value)/COUNT(impressions))
, mais sur des sous-ensembles de données, comme "Gains par impression où browser == 'Firefox'". L'objectif est de produire quelque chose comme "Votre EPC global est de 0,50 $, mais où browser ==" Firefox ", votre EPC est de 1,00", de sorte que l'utilisateur final peut rapidement voir des facteurs importants dans leurs données.
Parce qu'il ya un très grand nombre de ces sous-ensembles (dizaines de milliers), et la production de rapports n'a besoin que d'inclure les données de synthèse, je précalcul l'EPC-par sous-ensemble avec une tâche cron de fond, et le stockage ces valeurs récapitulatives dans la base de données. Une fois dans chaque 2-3 hits, un Hit doit interroger la table Hits pour d'autres Hits récents par un Visiteur (par exemple "find the REFERER du dernier Hit"), mais généralement, chaque Hit n'effectue qu'un INSERT, donc pour garder la réponse fois, j'ai divisé l'application sur 3 serveurs [bgprocess, mysql, hitserver].
À l'heure actuelle, j'ai structuré tout cela en 3 tables normalisées: Hits, événements et visiteurs. Les visiteurs sont uniques par session de visiteur, un hit est enregistré chaque fois qu'un visiteur charge une bannière ou clique, et les événements mappent la relation plusieurs-à-plusieurs des visiteurs aux hits (par exemple, un événement est "Visiteur X à la bannière Y" ", qui est unique, mais peut avoir plusieurs hits). La raison pour laquelle je conserve toutes les données de hit dans la même table est parce que, alors que mon exemple ci-dessus ne décrit que "Banner impressions -> clickthroughs", nous suivons également "clickthroughs -> pixel feux" clickthrough "et" second clickthrough -> pixel de la page de vente ".
Mon problème est que la table des hits se remplit rapidement, et ralentit ~ linéairement avec la taille. Mes données de test n'ont que quelques milliers de clics, mais mon traitement en arrière-plan ralentit déjà. Je peux lancer plus de serveurs, mais avant de lancer l'alpha, je veux m'assurer que ma logique est bonne.
Alors je vous demande SO-gourous, comment structureriez-vous ces données? Suis-je fou d'essayer de calculer toutes ces tables? Puisqu'il est rare que je doive accéder aux enregistrements Hit de plus d'une heure, est-ce que je pourrais partager la table Hits avec ProcessedHits (avec toutes les données historiques) et UnprocessedHits (avec les données de la dernière heure) ou faire indexer la colonne Hit.at Date? ce superflu?
Cela a probablement besoin d'une certaine élaboration, désolé si je ne suis pas clair, je travaille depuis ~ 3 semaines directement sur ce point jusqu'à présent :) TIA pour toutes les entrées!
Ceci est une réponse géniale, merci! J'utilise MyISAM et je cours tout sur EC2. À l'heure actuelle, le serveur Web et bgprocess sont sur de petites instances, avec MySQL sur une instance moyenne. La charge est tout sur le serveur bgprocess; Comme je l'ai dit, je peux le faire évoluer, mais je m'attends à ce que cela dépasse les données de test. Je n'avais pas du tout pensé au mouvement de la tête de disque, mais la table Hits and Events utilise des touches d'incrémentation; est-ce que vous voulez dire en insérant à la fin de la table? En ce moment, j'utilise l'ORM de Django pour toutes mes requêtes; Je suppose que je devrais les réécrire à la main? – linked
Oui, les clés d'incrémentation devraient mettre de nouveaux enregistrements à la fin de la table (alors qu'une clé de chaîne ne le ferait probablement pas). Les ORM peuvent être géniaux pour un développement rapide, mais ils peuvent aussi être très bavards. Si cela finit par être * trop * bavard, il vaut généralement la peine de réécrire les requêtes si vous le pouvez. – RickNZ