#1 Wed 01 February 2012 10:04
- Squid
- Participant actif
- Date d'inscription: 2 Apr 2010
- Messages: 109
[PostgreSQL/PostGIS] Creation d'index
Bonjour,
toujours dans une recherche de gain de performances, je souhaite créer un ou des index pour la requête suivante :
Code:
CREATE OR REPLACE FUNCTION prof_bathy5(cle int) RETURNS SETOF int AS $$ DECLARE rec record; ma_var int; BEGIN FOR rec IN EXECUTE ('SELECT elevation FROM report_pt_simple pt, bathymetry bathy where gid='||cle||' group by elevation,bathy.geogr,pt.geogr,bathy.the_geom,pt.the_geom having ST_Distance(geography(ST_closestpoint(bathy.the_geom,pt.the_geom)),pt.geogr)=(SELECT min(ST_Distance(geography(ST_closestpoint(ba2.the_geom, pt2.the_geom)), pt2.geogr)) FROM report_pt_simple pt2, bathymetry ba2 where gid='||cle||') ') LOOP ma_var:=rec.elevation; RETURN NEXT ma_var; END LOOP; END; $$ LANGUAGE plpgsql; BEGIN; SELECT fr.profondeur, pt.* FROM (SELECT prof_bathy5(gid) as profondeur, gid FROM report_pt_simple where gid between 1 and 200 )fr, report_pt_simple pt where pt.gid=fr.gid ;
cette requête prend 13s pour 50 enregistrements et 4 min pour la totalité des enregistrements !
C'est pourquoi je souhaite créer des index.
J'ai utilisé la méthode suivante sans résultats significatif.
Pouvez vous m'indiquer sur quels champs faire mes index et si je dois appeler mes index dans mes requêtes SELECT?
Merci
Hors ligne
#2 Wed 01 February 2012 11:24
Re: [PostgreSQL/PostGIS] Creation d'index
Bonjour,
toujours dans une recherche de gain de performances, je souhaite créer un ou des index pour la requête suivante :Code:
CREATE OR REPLACE FUNCTION prof_bathy5(cle int) RETURNS SETOF int AS $$ DECLARE rec record; ma_var int; BEGIN FOR rec IN EXECUTE ('SELECT elevation FROM report_pt_simple pt, bathymetry bathy where gid='||cle||' group by elevation,bathy.geogr,pt.geogr,bathy.the_geom,pt.the_geom having ST_Distance(geography(ST_closestpoint(bathy.the_geom,pt.the_geom)),pt.geogr)=(SELECT min(ST_Distance(geography(ST_closestpoint(ba2.the_geom, pt2.the_geom)), pt2.geogr)) FROM report_pt_simple pt2, bathymetry ba2 where gid='||cle||') ') LOOP ma_var:=rec.elevation; RETURN NEXT ma_var; END LOOP; END; $$ LANGUAGE plpgsql; BEGIN; SELECT fr.profondeur, pt.* FROM (SELECT prof_bathy5(gid) as profondeur, gid FROM report_pt_simple where gid between 1 and 200 )fr, report_pt_simple pt where pt.gid=fr.gid ;cette requête prend 13s pour 50 enregistrements et 4 min pour la totalité des enregistrements !
C'est pourquoi je souhaite créer des index.
J'ai utilisé la méthode suivante sans résultats significatif.
Pouvez vous m'indiquer sur quels champs faire mes index et si je dois appeler mes index dans mes requêtes SELECT?
Merci
Bonjour,
Il faudrait déjà décorréler la partie plpgsql de la partie SQL à proprement parler.
Le plpgsql et les boucles, c'est particulièrement peu rapide. Si on peut s'en passer complètement c'est encore mieux.
L'analyse de perf se fait ensuite sur la requete SQL pure, avec EXPLAIN pour identifier les points problématiques.
A vue de nez, vous n'avez aucune fonction spatiale qui peut utiliser les indexes, donc les ajouter ne va pas changer grand chose. Il faudrait regarder plus en détail mais souvent on peut remplacer du st_distance par du st_dwithin, ou avoir les deux, ce qui permet d'utiliser les indexes.
Il faut évidemment un index sur le champ gid, mais si c'est une PK il doit y être déjà.
Ensuite si on lit tous les enregistrements d'une table, ajouter des indexes ne changera rien, l'optimisation se fait plutot sur le matériel de stockage et la mémoire dans ce cas.
J'espère que ces quelques pistes vous aideront.
Hors ligne
#3 Wed 01 February 2012 17:31
- Squid
- Participant actif
- Date d'inscription: 2 Apr 2010
- Messages: 109
Re: [PostgreSQL/PostGIS] Creation d'index
Merci,
en tenant compte de vos conseils et en m'intéressant à l'exemple de ST_dwithin, je suis arrivé à cette requête qui donne les mêmes résultats
Code:
SELECT mm.* FROM (SELECT DISTINCT ON (gt.gid) gt.gid, gt.dob_cm, gt.elevation elevation FROM (SELECT gid, dob_cm,elevation, h.the_geom geoba,s.the_geom geopt, s.geogr geogrpt FROM report_pt_simple s ,bathymetry h) gt ORDER BY gt.gid, ST_Distance(geography(ST_closestpoint(geoba,geopt)),geogrpt)) mm;
Je me rend compte que la sous requête
Code:
(SELECT gid, dob_cm,elevation, h.the_geom geoba,s.the_geom geopt, s.geogr geogrpt FROM report_pt_simple s ,bathymetry h)
est répétée autant de fois qu'il y a d'enregistrements. Comment mettre en variable le résultat d'un produit cartésien pour qu'il ne soit éxécuté qu'une fois?
D'autre part je n'arrive toujours pas à configurer mon serveur.
Merci.
Dernière modification par Squid (Wed 01 February 2012 17:31)
Hors ligne
#4 Wed 01 February 2012 18:22
Re: [PostgreSQL/PostGIS] Creation d'index
Merci,
en tenant compte de vos conseils et en m'intéressant à l'exemple de ST_dwithin, je suis arrivé à cette requête qui donne les mêmes résultatsCode:
SELECT mm.* FROM (SELECT DISTINCT ON (gt.gid) gt.gid, gt.dob_cm, gt.elevation elevation FROM (SELECT gid, dob_cm,elevation, h.the_geom geoba,s.the_geom geopt, s.geogr geogrpt FROM report_pt_simple s ,bathymetry h) gt ORDER BY gt.gid, ST_Distance(geography(ST_closestpoint(geoba,geopt)),geogrpt)) mm;Je me rend compte que la sous requête
Code:
(SELECT gid, dob_cm,elevation, h.the_geom geoba,s.the_geom geopt, s.geogr geogrpt FROM report_pt_simple s ,bathymetry h)est répétée autant de fois qu'il y a d'enregistrements. Comment mettre en variable le résultat d'un produit cartésien pour qu'il ne soit éxécuté qu'une fois?
C'est surtout que cette sous requête fait une jointure complète.
Mais il faudrait réécrire l'ensemble en passant la sous requête directement dans la requête principale. Elle n'a à priori aucune raison d’être tel que c'est écrit ici.
Maintenant si vous faite une requete avec un produit cartésien complet sur des tables volumineuses, sans filtre, et avec un order by, ce sera long de toutes façons. Mais pour avancer ensuite il faut connaitre la donnée et le but réel recherché.
D'autre part je n'arrive toujours pas à configurer mon serveur.
C'est encore un thème à part entière, et qui dépend fortement de la typologie d'utilisation de la base de données, et du matériel sous jacent.
Hors ligne