une précision sur la fonction count de mysql

stephan69
Invité n'ayant pas de compte PHPfrance

19 sept. 2007, 13:28

Bonjour,

Je voudrais savoir si vous connaissiez le cout de la fonction count...
Il semblerait que cette fonction dans une requête necessite beaucoup de CPU lorsque que la requete interroge une table de grosse taille ( à peu près plus de 300 000 lignes).

Une telle requête met a peu pres 6 sec à s'executer... Mais comment puis je en être sur.
En effet, pour une application de doit regarder si cette requete est indispensable ou pas.

Merci

d0m
Mammouth du PHP | 1141 Messages

19 sept. 2007, 13:38

$temps_avant_requete = time();
mysql_query("Count.....");
$temps_apres_requete = time();
echo 'duree de la requete : ' . ($temps_avant_requete-$temps_apres_requete);

stephan69
Invité n'ayant pas de compte PHPfrance

19 sept. 2007, 13:43

Oui je sais je sais,
Je ne cherche pas du code, je cherche des informations sur le comportement de count...

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

19 sept. 2007, 14:00

La fonction COUNT(*) seule est la plus optimisée du langage SQL. En effet, chaque table connait le nombre d'enregistrement qu'elle contient et n'a pas besoin d'être parcourue pour le retourner.

Ce n'est pas donc elle qu'il faut incriminer, mais peut être plus de jointures, de conditions WHERE, des group by où d'order qu'il peut y avoir dans ta requête... Exécute ta requête en ajoutant EXPLAIN devant pour avoir plus d'info sur les index utilisés et le nombre d'enregistrements lu.
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Stephan69
Invité n'ayant pas de compte PHPfrance

19 sept. 2007, 14:08

OKOK,

EN fait, je viens de comprendre, il semblerait que ma table ne soit pas bien fait: Je ne suis meme pas sur qu'elle soit en 1FN.
Sije me souviens bien pour etre en 1FN il faut au moins une clé primaire et que chaque attribut soit monovalué...

Est ce qu'un champ text est monovalué? est ce qu'un champs contenant mot1#mot2m#mot3 l'est aussi?
pour le champs texte je pense que oui pour l'autre je ne sais pas trop...

merci

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

19 sept. 2007, 15:44

La première forme nécessite effectivement une clé et que les attributs de ta table soient atomiques, c'est à dire non décomposables (comme un champ adresse que tu pourrais décomposer en numéro, cp, ville, etc.)

Mais cela ne devrait pas impacter les performances du count. A la limite montre nous la structure de ta table et la requête que tu joues :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Stephan69
Invité n'ayant pas de compte PHPfrance

19 sept. 2007, 17:35

Salut voila la table et quelques explication.

Code : Tout sélectionner

Field Type Null Key Default Extra ContenuID int(11) unsigned PRI 0 Categorie tinyint(3) unsigned PRI 0 Keyword varchar(255) dtPublication datetime MUL 0000-00-00 00:00:00 Langue tinyint(3) YES NULL Type tinyint(3) unsigned 0 Contenu text YES MUL NULL Emetteur tinyint(3) unsigned YES NULL Valid tinyint(3) YES NULL Explication des différents champs : NomPage est le nom de la page Titre est le titre des articles, interviews, news Keyword est la concaténation des champs ISIN des interviews, news et des mots clés associés aux articles, interviews… dtPublication est la date et l’heure de mise en ligne des articles, interview… Langue correspond à la langue du texte. ContenuID correpond à L’ID du contenu (Chaque article possède un unique ID ainsi que chaque news et chaque interview). Catégorie est un entier compris entre [1,3] 1 pour un article 2 pour une interview 3 pour une news Type nous renseigne sur le type de catégorie. La base de données comprend des interviews d’experts, de président, des articles dits rumeurs…. Contenu correspond à la concaténation du sous titre, du chapeau et du texte d’un article, interview et news… Emetteur aura soit la valeur 0 pour une news Dj soit la valeur 1 pour une news R. Il sera nul pour tout autre catégorie. Valid est un entier qui en fonction de la valeur nous renseignera sur le fait que le contenu est en ligne ou va l’être.
Après une relecture, il semble bien que ma table soit en 3FN car tous les attibuts dépendent directement et exclusivement de la clée.

Si vous remarquez des incohérence, merci de me prevenir

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

19 sept. 2007, 18:43

COUNT() en elle-même n'est pas le problème, la fonction ne fait rien, c'est l'accès au données qui compte. Regarde du côté d'EXPLAIN et poste-nous le résultat sur ta requête de 6s.
chaque table connait le nombre d'enregistrement qu'elle contient et n'a pas besoin d'être parcourue pour le retourner
Attention, ça ce n'est valable que pour MyISAM, InnoDB n'a qu'une estimation du nombre d'enregistrements à cause du MVCC donc un COUNT(*) sans WHERE se fait par un full-table scan autant que je me rappelle.

Stephan69
Invité n'ayant pas de compte PHPfrance

20 sept. 2007, 12:17

Ok,

Mais nous avons abandonne l idee de faire une requete count.
Merci quand meme.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

20 sept. 2007, 12:35

Si vous avez abandonné l'idée à cause des performances, c'est à mon avis une énorme erreur. Un COUNT(*) qui prend 6s ça ne se voit que sur une table comportant des millions d'enregistrements, vous n'utilisez probablement pas d'index. Mais bon, sans schéma et sans requête c'est sûr que c'est plus dur de se faire une idée.