|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||||
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
Bonjour,
Voici la structure de ma table : Code :
Code :
- colX = col1 ou col2 ou col3 ou col4. - mavaleur = un string d'au moins 4 caractères. - baselist = liste des bases possible 3 cas possible : + 'E' + 'A' + 'E','A'La table contenant plus de 1,5Millions de ligne. Mon problème est que lorsque je réalise une requête pour la première fois sur une colonne (ex :col1) où la valeur est de 4 caractères et le nombre d’occurrences de cette valeur dans la table est important (plus 50 000). Ma requête dure plus de 3 min. Par contre une fois cette requête réalisée le temps de réponse sur la même requête est de moins d'une seconde (merci l'indexation je suppose). Je souhaiterai donc savoir si ce comportement est normal ? D'après ce que je crois avoir compris, lors de la première exécution de la requête postgres vérifie si le plan d'exécution existe déjà, évalue s'il est plus rapide de passer par les index. Comme dans mon cas il n'y a pas eu d'indexation sur cette requête postgres doit se taper toute la table et faire l'indexation (ce qui prendrait du temps je suppose). Du coup y a-t-il des moyens de gagner du temps sur cette première indexation ? Peut être ai-je mal compris si oui quelqu'un pourrait-il m'expliquer le mécanisme d'indexation succinctement et m'aider à trouver une solution ? Merci d'avance, DD |
||||
|
|
00
|
|
|
#2 |
![]() ![]() |
L'indexation est faite lorsque tu crées l'index et elle est mise à jour quand tu fais des ajouts, modifications, suppressions de données.
Lorsque tu lances une requête, le SGBD évalue quel(s) index il est intéressant d'utiliser. Ce qui fait que ta requête s'exécute plus vite à partir de la deuxième fois où tu la lances, c'est que le SGBD a encore en mémoire la requête et le résultat et regarde juste si un événement a pu modifier le résultat entre deux appels de la requête. Si ce n'est pas le cas, il donne le résultat qu'il a en mémoire sans exécuter une nouvelle fois la requête. Du moins, je crois que c'est comme ça que ça se passe. Ce qui plombe peut-être l'exécution de ta requête, c'est le ORDER BY sur une colonne non indexée.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française ! Linuxiens, comptez-vous ! |
|
00
|
|
|
#3 | ||||||
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
Bonjour,
J'ai bien suivi vos conseils mais cela n'a pas amélioré les performances. Voici mes manipulations : Code :
Code :
Pour information voici le résultat de mon EXPLAIN : Code :
D'autres idées ou raisons sur cette lenteur ? |
||||||
|
|
00
|
|
|
#4 | |
![]() ![]() |
Je ne suis pas habitué des EXPLAIN de Postgresql mais je vois ceci dans la requête :
et cela dans l'EXPLAIN : Citation:
Ton résultat escargot de 3mn12 est obtenu en lançant la requête directement sur le serveur ou via un programme applicatif ?
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française ! Linuxiens, comptez-vous ! |
|
|
00
|
|
|
#5 |
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
En fait j'ai pas copié la bonne requête, c'est juste que j'avais réalisé une autre requête avec "LES %".
L'EXPLAIN est bon. Je suis en train de plancher sur une modification de mes index du type : Code :
CREATE INDEX "idx_matable_col1" ON "monschema"."matable" (col1 varchar_pattern_ops); - http://www.postgresql.org/docs/8.1/s...s-opclass.html |
|
|
00
|
|
|
#6 |
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
Apparemment pas d'amélioration avec cette indexation...
Quelqu'un aurait une autre idée ? |
|
|
00
|
|
|
#7 |
|
Membre Expert
![]() Inscription : mars 2005 Messages : 1 565 ![]() |
EXPLAIN ANALYZE au lieu d'un simple EXPLAIN pour avoir plus d'informations.
|
|
|
00
|
|
|
#8 | ||||||||
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
Ci-dessous les deux cas de requêtes que j'ai testé. Mais aucune amélioration dans les 2 cas.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Avec les index simple : Code :
Code :
Avec les index suivant : Code :
Code :
Des suggestions ? |
||||||||
|
|
00
|
|
|
#9 |
![]() ![]() Inscription : octobre 2008 Messages : 1 508 ![]() |
D'après cette ligne:
Code :
INDEX Scan USING idx_matable_col1 ON matable (cost=0.00..16.59 rows=3 width=1491) (actual time=24.563..240824.383 rows=24570 loops=1) Le temps 24.563...2480824 veut dire que le 1er résultat est obtenu au bout de 24s et le dernier au bout de 240824s, donc l'essentiel du temps d'exécution est passé dans cette opération. Pour améliorer les stats, tu peux essayer d'augmenter la taille de l'échantillon avec ALTER TABLE .. ALTER COLUMN.. SET STATISTICS 1000 sur les colonnes col1 et base. 1000 est une valeur élevée, par défaut c'est 10 avec les versions assez anciennes de postgres et je crois 100 avec des versions relativement récentes. Ensuite faire un ANALYZE pour que ces stats soient recalculées (ne pas faire de VACUUM FULL qui est plutôt contre-productif pour les index sauf si on fait un REINDEX derrière). |
|
|
00
|
|
|
#10 |
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
Ok merci merci pour ces conseils éclairés, je m'en vais tout de suite tester.
Je vous tiens au courant. |
|
|
00
|
|
|
#11 |
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Pourquoi ne pas rajouter "base" en première position de chacun des quatre index ?
Si les valeurs de base sont exclusivement E ou A, au pire, dans le cas où il est égale à "E, A" alors 100% de l'index sera lu pour rechercher le like. Mais quand il sera E ou A, virtuellement, la moitié de l'index ne sera pas lu : c'est tout de même une bonne optimisation. Si le champ peut contenir d'autres valeurs, alors tu devrais gagner encore plus. Aussi, l'index sur datecreation ne sert à rien selon moi : vu qu'il utilise un autre index pour la recherche, il ne va pas utiliser un second index pour trier le résultat, qui n'est plus une image de ce qu'il y a dans la table. A nouveau, il faudrait rajouter datecreation à la fin dans tes quatres premiers index. => Ceci dit, je ne pense pas que ça change grand chosE. |
|
|
00
|
|
|
#12 | ||||
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
Bonjour,
Tout d'abord merci à tous pour votre aide.
|
||||
|
|
00
|
|
|
#13 |
|
Membre Expert
![]() Inscription : mars 2005 Messages : 1 565 ![]() |
Vous avez encore changé des choses dans la structure de vos tables. On a maintenant une colonne "liasse" ainsi qu'un index dont on a pas la définition.
Vous dites que la requête met 1mn à s'exécuter alors que l'explain indique 2s. Merci d'être plus précis dans les éléments que vous fournissez. Pour ce qui est des colonnes à indexer, je ne pense pas que mettre la colonne base en premier aide les performances. Cette colonne de doit pas être la plus discriminante et la dénomination semble une meilleure candidate. Pour ce qui est de la colonne date création, idem, je ne pense pas que l'inclusion à l'index aide les performances car il ne sera pas utilisable directement vu les filtres sur les autres colonnes. A tester. |
|
|
00
|
|
|
#14 | ||||
|
Invité de passage
![]() Inscription : février 2009 Messages : 25 ![]() |
Bonjour,
Pour résumer j'ai donc placé des statistiques importantes sur les colonnes les plus utilisées : Code :
Puis j'ai mis mes index comme suit : Code :
- requête pour la recherche : Code :
SELECT * FROM monschema.matable WHERE colx LIKE 'unevaleur%' AND codesite IN ('004') AND base IN ('E', 'A') ORDER BY datecreation DESC LIMIT 150 où base peut être : ('E') ou ('A') ou ('E', 'A') où codesite peut être une liste ou pas d'une dizaine de valeur de type 'XXX' Sachant que la valeur la plus complexe à rechercher est col1. - requête pour afficher un résultat : Code :
SELECT * FROM monschema.matable WHERE col2='mavaleur' AND datecreation='20060401' J'ai de bonne performances : je suis passé à environ 8s sur la première recherche de termes complexes. Cela vous parait-il normal ? |
||||
|
|
00
|
Copyright © 2000-2012 - www.developpez.com