2010-04-15 8 views
1

Je suis sur une pile LAMP pour un site Web que je gère. Il est nécessaire de regrouper les statistiques d'utilisation (une variété de choses liées à notre produit de bureau).Processus de statistiques de longue durée - réflexions sur le choix de la langue?

J'ai d'abord abordé le problème avec PHP (étant donné que j'avais déjà un tas de classes pour travailler avec les données). Tout a bien fonctionné sur ma boîte de dev qui utilisait 5.3. En bref, la gestion de la mémoire 5.1 semble être bien pire, et j'ai dû faire beaucoup de tromperie pour que les scripts de roll-up à long terme s'exécutent dans un espace mémoire fixe. Nos serveurs ne veulent pas mettre à jour PHP en ce moment. Depuis, j'ai ramené mon serveur dev à 5.1 pour ne plus rencontrer ce problème. Pour explorer des bases de données MySQL pour compiler des statistiques pour différentes périodes et résolutions, en exécutant potentiellement un processus qui le fait tout le temps dans le futur (par opposition à un calendrier cron), quel choix de langue recommandez-vous? Je regardais Python (je le sais plus ou moins), Java (je ne le connais pas très bien), ou je le faisais avec PHP (je le connais très bien).


Edit: clarification de conception pour commentateur

Résolutions: La façon dont fonctionne le script actuellement Rollup, est que j'ai des cours pour définir des résolutions et des seaux. J'ai l'année, le mois, la semaine, le jour - étant donné un «numéro de compartiment», chaque classe donne un horodatage de début et de fin qui définit la plage de temps pour ce compartiment - basé sur une date d'époque arbitraire. Le système maintient des enregistrements "complets", c'est-à-dire qu'il complètera son ensemble de données enroulé pour chaque résolution depuis la dernière fois qu'il a été exécuté, actuellement. SQL Strat: Les statistiques de base se trouvent dans de nombreux schémas et tables dissemblables. Je fais des requêtes individuelles pour chaque statistique enroulée pour la plupart, puis remplis un enregistrement pour insertion. Votre suggérez sous-requêtes imbriquées telles que:

INSERT dans rolled_up_stats (someval, someval, someval, ...) VALUES (SELECT SUM (somestat) de someschema, SELECT AVG (somestat2) de someschema2)

Ces sous-requêtes va générer des tables temporaires, non? Mon expérience a été lente comme la mélasse dans le passé. Est-ce une meilleure approche?

Edit 2: Ajout des réponses inline à la question

La langue était un goulot d'étranglement dans le cas de 5,1 php - je essentiellement ai dit que je fait le choix de mauvaise langue (bien que les scripts fonctionnait bien sur 5.3). Vous parlez de python, que je vérifie pour cette tâche. Pour être clair, ce que je fais est de fournir un outil de gestion pour les statistiques d'utilisation d'un produit de bureau (les journaux sont réellement écrits par un serveur EJB aux tables mysql). Je fais l'analyse de dossier de notation d'apache, aussi bien que plus de reportage de Web sur le côté Web, mais ce projet est séparé. L'approche que j'ai prise jusqu'ici est des tableaux agrégés. Je ne suis pas sûr de ce que ces produits de file d'attente de messages pourraient faire pour moi, je jetterai un coup d'oeil. Pour aller un peu plus loin - les données sont utilisées pour représenter l'activité dans le temps au niveau du service et du client, pour permettre à la direction de comprendre comment le produit est utilisé. Vous pouvez sélectionner une période (du 1er avril au 10 avril) et extraire un graphique du nombre total de minutes d'utilisation d'une certaine entité à différentes granularités (heures, jours, mois, etc.) en fonction de la période sélectionnée. C'est essentiellement une analyse après-coup de l'utilisation.Le besoin semble tendre vers le temps réel, cependant (regardez la dernière heure d'utilisation)

+0

1. Pourquoi voulez-vous que cela dure longtemps? Pourquoi le fonctionnement périodique de cron-job n'est-il pas suffisant? 2. J'ai supposé que les scripts de roll-up exécutaient un SQL comme "INSERT INTO RolledUpTable SELECT SUM (quelque chose) de RawTable GROUPBY Element_id" ou une telle, mais vous semblez impliquer que les scripts de roll-up lisent l'information dans le processus , traitez-les, puis poussez-les dans la base de données. Cela ressemble à un choix de conception étrange. S'il vous plaît clarifier votre question :) – moshez

+0

clarifications ajoutées ... sorte de spawns une question distincte si ;-) – Josh

+0

En outre, il ne doit pas nécessairement être long terme. La raison pour laquelle je pensais que cela pourrait être une bonne approche est que, après avoir utilisé le système, les gens sont déjà intéressés par les données en temps quasi réel à une résolution horaire. Peut être une demande déraisonnable, mais en supposant que ce ne soit pas, un travail cron ne semble pas couper la moutarde. – Josh

Répondre

1

Il y a beaucoup d'approches différentes à ce problème, dont certaines sont mentionnées ici, mais ce que vous faites avec les données le post-rollup n'est pas clair ...? Si vous souhaitez utiliser ces données pour fournir des boutons Digg de type X Diggs sur votre site, ou des graphiques récapitulatifs ou quelque chose comme ça qui doit être disponible sur une base continue, vous pouvez utiliser memcache pour ceci, et demandez à votre code de garder à jour la clé de cache pour la statistique en question en l'incrémentant aux moments appropriés.

Vous pouvez également conserver des tables d'agrégation dans la base de données, ce qui peut s'avérer utile pour des rapports plus complexes. Dans ce cas, selon la quantité de données dont vous disposez et vos besoins, vous pouvez obtenir une table horaire, puis créer des vues basées sur cette table pour représenter les jours, les semaines, etc.

Si vous avez des tonnes et des tonnes de données et que vous avez besoin de tables agrégées, vous devriez regarder dans la collection de statistiques de déchargement (et peut-être les requêtes de base de données elles-mêmes) vers une file d'attente comme RabbitMQ ou ActiveMQ. De l'autre côté de la file, mettez un démon consommateur qui reste et s'exécute tout le temps, en mettant à jour les choses dans la base de données (et peut-être le cache) si nécessaire.

Les journaux de votre serveur Web peuvent également vous intéresser. J'ai vu des cas où j'étais capable d'obtenir une partie importante des statistiques requises du serveur Web se connecte après quelques modifications mineures aux règles de format de journal dans la configuration. Vous pouvez faire rouler les journaux tous les, puis commencer à les traiter hors ligne, en enregistrant les résultats dans une base de données de rapports.

J'ai fait toutes ces choses avec Python (j'ai publié loghetti pour traiter les journaux de format combiné Apache, en particulier), bien que je ne pense pas que le langage soit un facteur limitant ou goulot d'étranglement ici. Ruby, Perl, Java, Scala, ou même awk (dans certains cas) fonctionneraient.

+0

La langue était un goulot d'étranglement dans le cas de PHP 5.1 - on m'a essentiellement dit que j'ai fait le mauvais choix de langue (bien que les scripts aient bien fonctionné sur 5.3). Vous parlez de python, que je vérifie pour cette tâche. Pour être clair, ce que je fais est de fournir un outil de gestion pour les statistiques d'utilisation d'un produit de bureau (les journaux sont réellement écrits par un serveur EJB aux tables mysql). Je fais l'analyse de dossier de notation d'apache, aussi bien que plus de reportage de Web sur le côté Web, mais ce projet est séparé. L'approche que j'ai prise jusqu'ici est des tableaux agrégés. Je ne suis pas sûr de ce que font ces produits MQ, je vais jeter un oeil. – Josh

+0

Pour aller un peu plus loin - les données sont utilisées pour tracer l'activité au fil du temps au niveau du service et du client, pour permettre à la direction de comprendre comment le produit est utilisé. Vous pouvez sélectionner une période (du 1er avril au 10 avril) et extraire un graphique du nombre total de minutes d'utilisation d'une certaine entité à différentes granularités (heures, jours, mois, etc.) en fonction de la période sélectionnée. C'est essentiellement une analyse après-coup de l'utilisation. Le besoin semble cependant tendre vers le temps réel (regardez la dernière heure d'utilisation) – Josh

0

Si vous exécutez des commandes principalement SQL, pourquoi ne pas simplement utiliser MySQL etc sur la ligne de commande? Vous pouvez créer une table simple qui répertorie les données agrégées, puis exécutez une commande telle que mysql -u[user] -p[pass] < commands.sql pour passer SQL à partir d'un fichier. Ou diviser le travail en plus petits morceaux et les exécuter séquentiellement (comme les fichiers PHP si c'est plus facile).

Si vous avez vraiment besoin d'un processus continu de longue durée, alors un langage de programmation comme python ou java serait mieux, puisque vous pouvez créer une boucle et la garder indéfiniment. PHP n'est pas adapté pour ce genre de chose. Il serait assez facile de convertir n'importe quelle classe PHP en Java.

+0

Voir la clarification de conception - J'ai ajouté des notes sur la façon dont les résolutions sont calculées pour maintenir un semblant de santé mentale quant à ce que les enregistrements correspondent à quelles périodes de temps sur tous les calcs. Quelque chose comme ceci est réalisable dans les requêtes raw sql ... ou peut-être y a-t-il une meilleure façon de gérer les résolutions? – Josh

1

J'ai travaillé sur un projet pour faire la même chose par le passé, j'ai donc une expérience réelle de la performance. Vous auriez du mal à battre les performances de "INSERT ... SELECT" (pas "INSERT ... VALUES (SELECT ...)".) Veuillez voir http://dev.mysql.com/doc/refman/5.1/en/insert-select.html

L'avantage est que si vous faites cela, en particulier si vous gardez le code de roll-up dans les procédures MySQL, c'est que tout ce dont vous avez besoin de l'extérieur est juste un cron-job pour pousser la DB à effectuer les bons roll-ups au bon moment - aussi simple qu'un shell-script avec « mysql <correct DB arguments etc.> "CALL RollupProcedure" »

de cette façon, vous vous garantissez zéro des bugs d'allocation de mémoire, ainsi que d'avoir des performances correctes lorsque le DB MySQL est sur une autre machine (sans déplacement de données sur la limite de la machine ...)

EDIT: résolution horaire est très bien - il suffit de lancer un cron-job horaire ...

+0

Désolé d'être un peu dork ici, je ne suis pas un ninja SQL. Je peux voir les avantages de la procédure stockée. Cependant, existe-t-il une solution pour les données couvrant plusieurs tables? Ou recommanderiez-vous une instruction INSERT ... SELECT pour chaque table qui nous intéresse? En outre, les résolutions de temps - avez-vous utilisé des périodes de roulement sur votre projet? IE, les dernières 24 heures, ou la dernière semaine? J'essaie d'utiliser des périodes fixes (du lundi au lundi est une semaine, par exemple). Les utilisateurs ont pensé que la sélection de lundi dernier à mercredi dernier avec une résolution de jour devrait leur donner exactement cela. Cela semble difficile avec les procédures stockées? – Josh