Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1
Hello,
Rien à voir avec le ZF
S'il y a bien une chose que je ne maîtrise pas, ce sont les SGBDR. Ha bien sûr je maîtrise les requêtes, mais pour ce qui relève des choix d'optimisation.....comme par ex. :
Vaut-il mieux, malgré la transgression de règles que ça implique, stocker les valeurs calculées dans des champs ?
Sur tous les sites qui gèrent des bibliothèques de médias, des compteurs sont donnés pour chaque type de ressource (nb. de médias, nb. de commentaires, nb. de votes, etc.). Mais qu'en est-il des performances ?
Mon premier réflexe est de stocker ces valeurs dans des champs, et au fond de moi je me sens mal de faire ça. De plus c'est très contraignant parce qu'à la moindre opération, une intervention du développeur (par le code) est nécessaire pour maintenir ces valeurs à jours, et autant dire qu'un simple delete devient une opération assez lourde.
J'ai envie de me convaincre de respecter les règles, de calculer ces valeurs à chaque affichage, de simplement ajouter une gestion du cache fine, mais ça fait PEUR :p
N'ayant aucun véritable professionnel de BDD autour de moi, j'aimerais savoir, parmis ceux d'entre vous qui gèrent de gros volumes, les choix que vous avez fait (et pourquoi)
Merci,
A+ benjamin.
Hors ligne
Salut,
En effet stocker la valeur count() dans un champ, tel quel ne me semble pas top.
Je pense que tu peux te permettre de calculer cette valeur à chaque fois mais avec un peu de cache et de logique.
Je pars de la supposition que tu as une table de log, dans laquelle tu insert un enregistrement avec date et identifiant pour chaque accès à la ressource que tu manipule.
Soit $row, un élément pour lequel tu veux afficher le nombre de vue.
Par réflexe tu ferais un : "select count(1) from log where row = $row" et mettre en cache le résultat.
Cela serait de plus en plus coûteux au fil du temps de manière linéaire par rapport au nombre de visiteurs sur le site.
Soyons philosophe : on ne peut changer le passé. Il a été, et restera toujours.
Par conséquent, le nombre de visite de la veille ne changera jamais, de même que le nombre de visite du mois dernier, et ainsi de suite.
Le nombre de vue de ta ressource n'est rien d'autre que la somme du nombre de vue pour chaque année où ton site a été en production.
Le nombre de vue pour une année donnée n'est rien d'autre que la somme du nombre de vue pour chaque mois de l'année.
Et ainsi de suite
Or excepté pour le siècle en cours, l'année en cours, le mois en cours, le jour en cours... tous les autres calculs peuvent être stocké de manière définitive.
Le calcul sera donc réduit à ce qui est en cours. Soit rien comparé aux milliers, voire millions de logs que tu vas avoir. Quand a ce dernier calcul, un petit cache de quelques secondes/minutes, ou bien quelques dizaines de hops, ne génerât pas dans de nombreux cas.
Après à toi de voir si tu stocke c'est calcul définitif au niveau du cache Zend, au niveau de ton SGBD (car tu a des accès direct vers celui-ci par des API, ...), au niveau d'un cache BDD, ...
À toi de voir aussi quelle granularité tu prends en fonction de tes ressources et de ton nombre de donnée à calculer :
- Siècle > Demie siècle > Décennie > Année > Semestre > Trimestre > Mois > Quinzaine > Semaine > jours > Demis journée > Heure > minutes
- Année > Mois > Jours > Heure > Minutes
D'un point de vue personnel, je suis partisan du stockage en BDD de ces calculs granulaires définitifs en BDD, pour générer facilement un dashboard de statistique en back-office.
Laurent.
Dernière modification par My_Sic (14-10-2010 12:48:19)
Hors ligne
Salut,
Ca dépend beaucoup du volume de ce que tu veux compter.
En général, en dessous de quelques dizaines de milliers de lignes (hors tables contenant un gros volume de donnée par ligne) tu peux considérer que le décompte est un amuse gueule pour des bases de données comme Mysql. Là où il fat tempérer ma réponse, c'est si tu as besoin de plusieurs tables pour calculer ton compteur. Si tu dois faire 3 ou 4 jointures sur des tables contenant des milliers de lignes alors tu risques de mettre mysql à genoux. Dans ces cas là il vaut mieux incrémenter et décrémenter au fur et à mesure.
Pour un vendeur de média (type librairie ou disquaire) si le nombre de référence est petit (par exemple les 5000 livres ou disques vendu par la boutique de quartier) tu peux considérer qu'il n'y aura surement pas de lenteurs dans les décomptes avant quelques années. Par contre pour un site comme amazon il vaut mieux stocker les compteur.
PS : Comme dit My_Sic, pour des statistiques tels que "visites par mois" destiné à une surveillance de l'évolution de visites, il vaut mieux les stocker en dur à chaque fin de mois même si on a juste 1000 visiteurs par mois. En même temps, pour ce genre de statistique, si on a accès aux logs du serveur, alors il vaut mieux utiliser des outils comme awstats qui sont très complet (tant qu'on ne veut pas des statistiques du genre "nombre de visite sur la section rock du forum" ) que de faire son propre système.
Hors ligne
Hello,
La consolidation des données n'est pas toujours possible.
Par ex. sur un de nos sites à forte charge nous conservons des statistiques journalières glissantes sur 30 jours. Ce qui nous permet de consolider ces données sur des périodes allant du mois à 30-n jours.
Pour un nombre de vues, le problème reste limité, puisque dans ce cas c'est effectivement une donnée pérenne dans le temps. Mais certaines statistiques, comme le nombre de commentaires, où le nombre d'éléments dans une collection ne sont pas invariables (une suppression de commentaire par ex.).
Dans le cas où les compteurs sont stockés, ça pose différents problèmes. Le premier, lors d'une suppression d'un commentaire par ex., il faut mettre à jour les statistiques (-1 sur la date du com.), mettre à jour le compteur dans la table des commentaires, etc.
Dans ce cas, on change donc le passé et cette donnée est tout sauf définitive.
En contre-partie, ça me semble difficile d'aller compter pour chaque affichage (je parle sans cache) le nombre de commentaires par un COUNT(1).
Admettons qu'une liste de ressources soit remontées selon un calcul complexe de popularité sur une période donnée, un COUNT ne peut pas être exécuté dans la requête de popularité, il doit être traité à part et ce pour chaque ressource dans la liste de résultats. Ce qui veut dire qu'en plus des quelques requêtes pour récupérer les ressources selon un classement il faudra en plus aller compter dans la table des commentaires autant de fois que j'ai de ressources, et il faut multiplier ça par le nombre de données de ce type qui doit être remontée pour chaque ressource.
Alors la question est, et c'est la qu'est mon ignorance, à partir de quand cela risque-t'il d'être problématique ? 1M de lignes ? 10M ? 100M ? Tant que nous n'avons pas expérimenté ça, ce genre de question est une torture
C'est pour ça que j'ai décidé de stocker ces valeurs et de les maintenir à jour manuellement, ce qui est une énorme contrainte, et peut-être que je le fais parce que je sous estime complètement la puissance de mon SGBDR, telle est la question
A+ benjamin.
Dernière modification par Delprog (14-10-2010 14:45:57)
Hors ligne
Hello,
Il y a quelque chose qui ne faut pas négliger, ce sont les index. Je travaille principalement avec Oracle (et donc ses outils de tuning/parsing). Les index sont très important.
J'avais récemment un job de mise à jour (PL/SQL exécuté 1 fois par jour) qui prenait environ 1mn quand la base était vide mais qui est monté à près d'une heure avec quelques centaines de milliers de lignes. En travaillant sur les index, je suis redescendu à 17s.
@+
Hors ligne
Oui il y a les indew mais il y aussi l'optimisation du sgbd . Tu peut pour mysql en le configurant correctement diminuer le temps d'exécution des requêtes. lien tu peut essayer le premier si tu est sous Mysql
Dernière modification par lebilien (14-10-2010 14:47:51)
Hors ligne
Merci pour vos réponses.
En fait ma question porte plutôt sur les bonnes pratiques pour ce type de valeurs calculées, pas tant sur l'optimisation de la base ou des index. J'essaie de savoir ce qui se pratique pour ne pas faire ça sur une intuition
A+ benjamin.
Hors ligne
Pour simplifier la gestion de compteurs tu peux utiliser les Triggers de ton SGDB. Par exemple lorsque tu ajoutes (INSERT) un commentaire, tu vas incrémenter le compteur associé. Et lorsque tu supprimes (DELETE) ton commentaire, tu vas désincrémenter ton compteur.
Comme ça, ça t'évite de devoir jouer manuellement avec le compteur.
Hors ligne
Le problème des triggers, c'est que ça peut devenir un casse tête monumental si on y prend pas garde. On a parfois autres chose à faire dans les triggers et certaines bases de données ont des limitations. Par exemple avec Mysql, on ne peut pas modifier les données présentent dans une table qui est en cours de modif par la requête SQL ou par un des triggers qui ont déclenché le trigger courant.
Dans certains cas, il est 100 fois plus simple de gérer les compteurs en php plutôt qu'en utilisant les triggers.
Finalement si on voulait résumer cette discussion on en reviendrait toujours à un "ça dépend des cas".
Hors ligne
Pages: 1