banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Rencontres QGIS 2025

L'appel à participation est ouvert jusqu'au 19 janvier 2025!

#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

vincentp
Participant actif
Lieu: Drôme
Date d'inscription: 18 Jul 2006
Messages: 128
Site web

Re: [PostgreSQL/PostGIS] Creation d'index

Squid a écrit:

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

vincentp
Participant actif
Lieu: Drôme
Date d'inscription: 18 Jul 2006
Messages: 128
Site web

Re: [PostgreSQL/PostGIS] Creation d'index

Squid a écrit:

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?


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é.


Squid a écrit:

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

 

Pied de page des forums

Powered by FluxBB