Listage Clients par 1ere Lettre mais extreme lenteur a la requete.

Eléphant du PHP | 168 Messages

27 août 2007, 16:19

Bonjour, je m'explique j'utilise afin de ranger mes clients un simple choix de lettre afin de lister que les derniers commmencant par celle ci.

Seul problème et pas des moindres, plus il y a de clients et plus la page met du temps a charger.

J'ai mis un index sur le nom du client, mais ca ne change rien.

Comment je pourrai proposer, optimiser tout ça.. actuellement cela ce réalise par un LIKE 'A%' par ex.

Merci d'avance.

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

27 août 2007, 16:27

Ben le problème du like, c'est que l'index n'est pas utilisé puisqu'il ne s'agit pas d'une recherche exacte... tu peux essayer avec un = SUBSTR(champ, 0, 1) pour récupérer la première lettre du champ.. je doute que l'index soit utilisé, mais tu verras peut être une amélioration au niveau performance...

Je déplace le sujet dans le forum SQL tu y obtiendras sans doute plus de réponses :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Invité
Invité n'ayant pas de compte PHPfrance

27 août 2007, 17:54

Je viens de tester, a premiere vue, je ne vois aucune différence.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

27 août 2007, 18:14

l'index n'est pas utilisé puisqu'il ne s'agit pas d'une recherche exacte
Attention, l'index peut être utilisé tant que le motif de recherche ne commence pas par un joker. Mais MySQL peut aussi choisir de l'ignorer s'il y a trop de résultats et chercher directement dans la table sans passer par l'index. En revanche, avec SUBSTR() c'est sûr, pas d'index dans les versions actuelles de MySQL (pas d'index sur les fonctions pour l'instant).

@Nico : tu n'as pas posté le schéma de tes tables... si c'est écrit en rouge à l'écran c'est vraiment que c'est indispensable pour répondre à ce genre de questions. Tant que tu y es, il faudrait que tu postes un EXPLAIN de chacune des requêtes que tu as essayé, merci.

Eléphant du PHP | 168 Messages

27 août 2007, 21:44

l'index n'est pas utilisé puisqu'il ne s'agit pas d'une recherche exacte
Attention, l'index peut être utilisé tant que le motif de recherche ne commence pas par un joker. Mais MySQL peut aussi choisir de l'ignorer s'il y a trop de résultats et chercher directement dans la table sans passer par l'index. En revanche, avec SUBSTR() c'est sûr, pas d'index dans les versions actuelles de MySQL (pas d'index sur les fonctions pour l'instant).

@Nico : tu n'as pas posté le schéma de tes tables... si c'est écrit en rouge à l'écran c'est vraiment que c'est indispensable pour répondre à ce genre de questions. Tant que tu y es, il faudrait que tu postes un EXPLAIN de chacune des requêtes que tu as essayé, merci.
Voici la structure de ma table.
Image

Voici la requete avec LIKE
Image

Voici la requete EXPLAIN (je ne sais pas l'interpreter) avec SUBSTR(SUBSTRING chez 1and1 pour changer -_-)
Image

Merci de l'aide.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

27 août 2007, 21:58

Euh, je n'ai pas pensé à le préciser, mais quand on parle de structure de la table c'est sous la forme d'une commande CREATE TABLE (dans l'onglet Exporter). Est-ce que tu pourrais poster ça stp ? Entre autres avantages, cette méthode a celui de nous permettre de créer la même table facilement, et surtout la commande indique les indices de la table, pas seulement les colonnes.

Eléphant du PHP | 168 Messages

27 août 2007, 22:03

Euh, je n'ai pas pensé à le préciser, mais quand on parle de structure de la table c'est sous la forme d'une commande CREATE TABLE (dans l'onglet Exporter). Est-ce que tu pourrais poster ça stp ? Entre autres avantages, cette méthode a celui de nous permettre de créer la même table facilement, et surtout la commande indique les indices de la table, pas seulement les colonnes.

Code : Tout sélectionner

CREATE TABLE `client` ( `id_client` mediumint(8) unsigned NOT NULL auto_increment, `nom_societe` varchar(100) NOT NULL default '', `adresse_client` varchar(255) NOT NULL default '', `cp_client` varchar(5) NOT NULL default '', `ville_client` varchar(255) NOT NULL default '', `lat_client` varchar(10) NOT NULL default '', `long_client` varchar(10) NOT NULL default '', `tel_fixe_client` varchar(15) NOT NULL default '', `tel_portable_client` varchar(15) NOT NULL default '', `tel_fax_client` varchar(15) NOT NULL default '', `prestation_client` text NOT NULL, `logo_client` varchar(50) NOT NULL default 'nologo.jpg', `video_client` text NOT NULL, `site_web_client` varchar(150) NOT NULL default '', `fiche_vue_client` smallint(5) unsigned NOT NULL default '0', `valider_client` tinyint(1) NOT NULL default '0', `date_inscription` datetime NOT NULL default '0000-00-00 00:00:00', `meta_description` varchar(255) NOT NULL default '', `secteur_activite_client` text NOT NULL, `promotions_client` text NOT NULL, `email_client` varchar(255) NOT NULL default '', PRIMARY KEY (`id_client`), KEY `nom_societe` (`nom_societe`) ) TYPE=MyISAM AUTO_INCREMENT=7759 ;
Voila, et qu'appelle tu indices. ?

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

27 août 2007, 22:05

indices = pluriel d'index

J'ai lu le résultat de tes EXPLAIN, dans le premier ("LIKE 'A%") on peut voir que les indices possibles (possible_keys) sont "nom_societe", et que l'index qui a été utilisé est "nom_société". Donc MySQL a bien choisi d'utiliser l'index associé. On voit aussi que la longueur de l'index est 100, ce qui est relativement long quand on pense que seul le premier caractère est utilisé. D'après l'EXPLAIN, il y a à peu près 665 enregistrements qui correspondent à 'A%'. La colonne "Extra" ne contient pas 'Using filesort' donc il semblerait que l'index est utilisé pour récupérer les enregistrements dans l'ordre.

D'après ce que je lis, la requête est quasi-optimale, combien de temps prend son exécution ? Combien de lignes sont retournées ? (l'index en prévoit ~665 mais quel est le compte réel ?)

Dernière chose, fais un OPTIMIZE TABLE au cas où. En règle générale, ça ne fait pas grand-chose, mais si tu as inséré/effacé de nombreux enregistrements ça peut aider. Autre astuce, si tu récupères le plus souvent les enregistrements par ordre alphabétique, tu peux les réorganiser pour qu'ils soient stockés dans cet ordre avec :

Code : Tout sélectionner

ALTER TABLE client ORDER BY nom_societe ASC
Là encore, les gains sont infinitésimaux, et la procédure est à répéter de temps à autres.

Eléphant du PHP | 168 Messages

27 août 2007, 22:11

Le nbre de resultat est pour le moment a peut pret egal a ca, mais cela va etre que croissant, actuellement je dirai que je n'ai inseré dans ma base client que 5 % de tous mes fiches clients.

Pour le temps de chargement je dirai 5/6 sec sur mon PC, mais x fois plus sur un pc plus vieux.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

27 août 2007, 22:19

Le problème vient probablement d'ailleurs. Même sur un PC très moyen, cette requête devrait prendre dans les 200ms max. D'ailleurs, je note que tu parles de "temps de chargement", si tu veux connaître le vrai temps d'exécution utilise le client MySQL (si tu as installé MySQL sur ton ordinateur) ou le temps affiché dans phpMyAdmin.

Eléphant du PHP | 168 Messages

27 août 2007, 22:23

Pense tu que afficher 400 clients juste une ligne par client peut ralentir l'affichage de la page ? dans tous les cas je ne vois pas comment filtrer plus que par lettre..

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

27 août 2007, 22:40

S'il s'agit d'un tableau HTML alors oui, 400 lignes prennent beaucoup de temps à être affichées. Utilise une pagination, 20 clients par page par exemple.

Eléphant du PHP | 168 Messages

28 août 2007, 11:34

Ca doit etre ça :).

Donc en final le SUBSTR sera plus rapide ou moins rapide que le LIKE ?

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

28 août 2007, 12:21

LIKE systématiquement plus rapide que SUBSTR()

Eléphant du PHP | 168 Messages

28 août 2007, 12:25

OK, merci de ton aide et de ce support avec pleines de volontée, c'est vachement agréable.