|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||||||||
|
Candidat au titre de Membre du Club
![]() Inscription : novembre 2006 Messages : 72 ![]() |
Sous Postgresql 8.2, PGadmin sous WindowsXP et Serveur sous Freebsd6.2.
J'ai deux tables A et B. A contient des ID en clef primaire. B contient des lignes d'info sur chaque ID de A (clef étrangère). Mon but est de récupérer toutes les lignes de B associés aux ID de A dont la liste est fournit. La premiere chose qui m'ai venu à l'esprit est d'utiliser IN: Code :
Etant sidéré par le résultat, j'ai tenté le OR (bin oui quoi, on ne sait jamais Code :
Le bourrin que je suis refait le même test avec des reqêtes SQL unique : Code :
Essayons maintenant avec une jointure: Code :
Comment expliquez-vous tout ceci? Y a t'il des implémentations à faire pour pouvoir utiliser la notation IN? Y a t'il des trucs que j'ai pas vu dans les explain? Ou bien est-ce là une preuve que l'utilisation de IN n'est pas optimale? |
||||||||
|
|
00
|
|
|
#2 |
|
Membre habitué
![]() Inscription : août 2007 Messages : 128 ![]() |
À ma connaissance, PG utilise les index dans le cas de IN. En tout cas, il est sûr qu'il peut les utiliser dans ton gros ensemble de OR.
Donc la première possibilité que je vois : les stats des tables ne sont pas à jour. Autre chose, quel sont les types de A.id et B.id ? |
|
|
00
|
|
|
#3 |
|
Candidat au titre de Membre du Club
![]() Inscription : novembre 2006 Messages : 72 ![]() |
J'avais fais un vacuum analize et un analize (pgadmin) sur B avant ces tests (excusez-moi de l'oublie :/). Je ne me rappelle pas l'avoir fait pour A. Bon apres avoir mis à jour avec ces 2 commandes sur les 2 tables cette fois : rien ne change.
Sinon, les identifiants sont des bigint pour B, et bigserial pour A. Se peut-il que ce soit lié une une configuration serveur? |
|
|
00
|
|
|
#4 |
|
Membre habitué
![]() Inscription : août 2007 Messages : 128 ![]() |
Configuration serveur, je ne pense pas.
As-tu essayé la requête IN en castant tous les nombres pour qu'ils soient explicitement des bigint ? je serais étonné que cela donne de meilleurs résultats, étant donné que ce problème a été corrigé pour les smallint sur les anciennes versions, mais malheureusement je n'ai rien d'autres à te proposer pour l'instant. Quelle volumétrie au niveau des tables A et B ? en terme de nombre de lignes et de taille ? Quelle taille pour l'index ? Et pourrait-on avoir la définition exacte des deux tables ? |
|
|
00
|
|
|
#5 | ||||
|
Candidat au titre de Membre du Club
![]() Inscription : novembre 2006 Messages : 72 ![]() |
Le castage en bigint ne change rien.
Table A: Code :
Taille de la table TOAST : 8192 bytes Taille Index : 56 KB Lignes éstimées : 462 Table B: Code :
Taille de la table TOAST : aucun Taille Index : 5778 MB Lignes éstimées : 57219300 |
||||
|
|
00
|
|
|
#6 |
|
Membre habitué
![]() Inscription : août 2007 Messages : 128 ![]() |
Tu es sûr de la taille de ton index ? J'ai dû mal à comprendre pourquoi PG s'embêterait à parcourir un index de 5G si la table elle-même est plus petite
As-tu fait un REINDEX de ton index dernièrement ? Enfin, peut-être ne considère-t'il pas l'utilisation d'un Index Bitmap Scan dans le cas d'un IN. Peut-être que la création d'un index sur id uniquement solutionnerait ton problème. Rien que pour le test, je serais très intéressé par ce résultat (si évidemment, tu as le temps de le faire). |
|
|
00
|
|
|
#7 |
|
Candidat au titre de Membre du Club
![]() Inscription : novembre 2006 Messages : 72 ![]() |
La définition d'une clef primaire ne definit-elle pas un index?
Il y a 5Gb d'index, mais il faut voir qu'il y a 3 index sur la table B! (id, trade_date et le couple (id,trade_date)). Pour ce qui est du REINDEX, oui j'en avais fait un. Je vais le refaire pour voir. |
|
|
00
|
|
|
#8 |
|
Membre habitué
![]() Inscription : août 2007 Messages : 128 ![]() |
Je crois que oui pour la première question. Cependant B.id n'est pas une clé primaire. La clé primaire de B est sur trois champs. Moi, je parlais d'un index sur id seul. Je ne vois que deux index sur ta table B : un sur id et trad_date et un autre sur trad_date seul.
Il serait aussi possible d'avoir la taille des deux index ? et la réponse à mon intervention précédente au vu des nouvelles infos données ci-dessus ? Merci. |
|
|
00
|
|
|
#9 | ||||||
|
Candidat au titre de Membre du Club
![]() Inscription : novembre 2006 Messages : 72 ![]() |
Haaaaaaaaaaaaa oui effectivement, j'ai confondu clef étrangere et primaire...
Merci, je viens d'apprendre ce que tu voulais dire par un "Index Bitmap Scan" qui est un scan d'index defini en multi-colonne et encore un oops : j'ai cru t'avoir deja mis les resultats du test avec l'index sur ID :/ Je le refais! Code :
J'ai tésté en changeant l'ordre des conditions ('IN' avant le '=') mais rien ne change. On voit aussi que ça se passe dans la premiere branche. Donc certainement lors de la construction de (A,B). Si je réécris ma requête pour limiter cette construction pour ce test: Code :
J'ai fais un chtit test pour voir ce que ça donne en remplaçant la condition d'égalité: Code :
Mais je ne vois toujours pas pourquoi il ne passe pas par un index pour repondre à une clause d'égalité entre deux colonnes de deux tables. (il fait des parcours sequentiels si j'enleve les clauses IN). Pour ce qui est des tailles de chaque index: Sur B: (id) => 1226MB (id, trade_date) => 1722MB (trade_date) => 1226MB |
||||||
|
|
00
|
|
|
#10 |
|
Membre habitué
![]() Inscription : août 2007 Messages : 128 ![]() |
J'avoue que je suis un peu sec là aussi. Il ne semble pas capable d'inférer que B IN X si A IN X AND A=B. Pour faire son hash, il a besoin de deux pseudos tables temporaires. Il en compose une en filtrant des éléments de A grâce au IN, et il prend B entièrement car il n'a pas de filtre spécifique sur B. Et seulement ensuite il fait son hachage. Étonnant.
En attendant, tu as une solution avec le A IN X AND B IN X AND A=B. Il faudrait voir si l'index sur B.id est toujours nécessaire. |
|
|
00
|
|
|
#11 |
|
Candidat au titre de Membre du Club
![]() Inscription : novembre 2006 Messages : 72 ![]() |
En attendant, et ça m'aide pour construire d'autres requêtes du même genre
Mais je ne vois pas comment utiliser les index dans le cas ci-dussous: SELECT * FROM A,B WHERE A.id=B.id; (aucune idée des ID) De plus, postgres n'utilise pas d'index pour les requêtes avec GROUP BY: SELECT id FROM A GROUP BY id; .. il fait un parcours sequentiel!! |
|
|
00
|
|
|
#12 |
|
Membre habitué
![]() Inscription : août 2007 Messages : 128 ![]() |
Pour la partie du GROUP BY, conceptuellement, je ne vois pas pourquoi il utiliserait un index. Sans compter que la table A est tellement petite que l'utilisation d'un index pour une quelconque opération n'est pas forcément une bonne idée en soi.
|
|
|
00
|
Copyright © 2000-2012 - www.developpez.com