Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 14-10-2010 10:50:56

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Gros volume de données : stocker count() dans un champ ou non ?

Hello,

Rien à voir avec le ZF smile

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) smile


Merci,
A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#2 14-10-2010 12:46:26

My_Sic
Membre
Date d'inscription: 06-09-2010
Messages: 49
Site web

Re: Gros volume de données : stocker count() dans un champ ou non ?

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)


http://www.centurion-project.org: Full stack Framework based on Zend Framework; led by:
http://www.octaveoctave.com: an enthusiastic web agency full of passionate.
http://www.cache-pistache.com: French blog on ZF and SF perfomance

Hors ligne

 

#3 14-10-2010 14:17:51

omega2
Membre
Lieu: Boisbriand, quebec, canada
Date d'inscription: 01-04-2009
Messages: 85
Site web

Re: Gros volume de données : stocker count() dans un champ ou non ?

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

 

#4 14-10-2010 14:30:56

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: Gros volume de données : stocker count() dans un champ ou non ?

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 smile

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 smile


A+ benjamin.

Dernière modification par Delprog (14-10-2010 14:45:57)


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#5 14-10-2010 14:35:24

mikaelkael
Administrateur
Lieu: Donges
Date d'inscription: 18-06-2007
Messages: 1176
Site web

Re: Gros volume de données : stocker count() dans un champ ou non ?

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.

@+


Less code = less bugs
Contributeur ZF - ZCE - ZFCE - Doc ZF (CHM & PDF) - Vice-trésorier AFUP 2011
Ubuntu 11.04 - ZendServer

Hors ligne

 

#6 14-10-2010 14:47:29

lebilien
Membre
Lieu: avranches
Date d'inscription: 19-06-2007
Messages: 270
Site web

Re: Gros volume de données : stocker count() dans un champ ou non ?

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)


http://www.parkaddict.com Gagner des places dans vos parcs préférés

Hors ligne

 

#7 14-10-2010 14:56:45

Delprog
Administrateur
Date d'inscription: 29-09-2008
Messages: 670

Re: Gros volume de données : stocker count() dans un champ ou non ?

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 smile


A+ benjamin.


http://www.anonymation.com/ - anonymation - Studio de création.
http://code.anonymation.com/ - anonymation - blog - développement et architecture web

Hors ligne

 

#8 14-10-2010 17:39:38

ndesaleux
Membre
Date d'inscription: 16-04-2007
Messages: 196
Site web

Re: Gros volume de données : stocker count() dans un champ ou non ?

J'aurais tendance pour les données non consolidées, j'aurais tendance à vouloir utiliser les vues.

Hors ligne

 

#9 14-10-2010 19:01:22

3uclide
Membre
Date d'inscription: 09-08-2008
Messages: 194

Re: Gros volume de données : stocker count() dans un champ ou non ?

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

 

#10 15-10-2010 05:12:30

omega2
Membre
Lieu: Boisbriand, quebec, canada
Date d'inscription: 01-04-2009
Messages: 85
Site web

Re: Gros volume de données : stocker count() dans un champ ou non ?

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

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages