#1 Thu 01 September 2011 15:18
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Optimisation de requĂȘte PostGIS
Bonjour,
j'ai un petit soucis d'optimisation d'une de mes requĂȘtes.
VoilĂ la situation,
J'ai 2 tables, une avec des parcelles et leur information et une avec des zones humides.
La seule chose qui lie mes 2 tables ce sont leurs multipolygones.
Ma requĂȘte consiste Ă connaitre toutes les parcelles qui sont en contact partiellement ou totalement avec une zone humide donnĂ©e
D'aprÚs les informations que j'ai glanées un peu partout, je pensais que je pouvais utiliser un opérateur spatial : &&
Ce qui donne en SQL :
Code:
select idparcelle from parcelle, zone_humide WHERE zone_humide.the_geom && parcelle.the_geom) AND zone_humide='670057'
Et lĂ jâobtiens pas du tout ce que je souhaite. Il me retourne des parcelles qui ne sont pas en contact avec la zone humide.
Par contre si j'utilise la fonction Intersects(), j'obtien de bon rĂ©sultat avec cette requĂȘte :
Code:
select idparcelle from parcelle, zone_humide WHERE Intersects(zone_humide.the_geom ,parcelle.the_geom) AND zone_humide='670057'
Le soucis c'est qu'avec la premiÚre j'ai un résultat en 1,5 secondes, avec la deuxiÚme : 2h35. (j'ai 50 millions d'entrées dans la table parcelle).
J'ai plus de 1500 zones humides à traiter donc là ... ça marche pas.
Est-ce qu'il y aurais un moyen pour optimiser la requĂȘte ?
D'avance merci pour votre aide.
Nebuka
Hors ligne
#2 Thu 01 September 2011 15:50
Re: Optimisation de requĂȘte PostGIS
Bonjour,
j'ai un petit soucis d'optimisation d'une de mes requĂȘtes.
VoilĂ la situation,
J'ai 2 tables, une avec des parcelles et leur information et une avec des zones humides.
La seule chose qui lie mes 2 tables ce sont leurs multipolygones.
Ma requĂȘte consiste Ă connaitre toutes les parcelles qui sont en contact partiellement ou totalement avec une zone humide donnĂ©e
D'aprÚs les informations que j'ai glanées un peu partout, je pensais que je pouvais utiliser un opérateur spatial : &&
Ce qui donne en SQL :Code:
select idparcelle from parcelle, zone_humide WHERE zone_humide.the_geom && parcelle.the_geom) AND zone_humide='670057'Et lĂ jâobtiens pas du tout ce que je souhaite. Il me retourne des parcelles qui ne sont pas en contact avec la zone humide.
Par contre si j'utilise la fonction Intersects(), j'obtien de bon rĂ©sultat avec cette requĂȘte :Code:
select idparcelle from parcelle, zone_humide WHERE Intersects(zone_humide.the_geom ,parcelle.the_geom) AND zone_humide='670057'Le soucis c'est qu'avec la premiÚre j'ai un résultat en 1,5 secondes, avec la deuxiÚme : 2h35. (j'ai 50 millions d'entrées dans la table parcelle).
J'ai plus de 1500 zones humides à traiter donc là ... ça marche pas.
Est-ce qu'il y aurais un moyen pour optimiser la requĂȘte ?
D'avance merci pour votre aide.
Nebuka
Bonjour,
As tu créé un index spatial sur tes colonnes gĂ©omĂ©triques ? Dans ce cas il faudra que tu utilises la fonction st_intersects(). Il me semble qu'utiliser l'opĂ©rateur spatial && peut ĂȘtre toujours utiliser. Celui-ci compare la bbox des gĂ©omĂ©tries et est donc complĂ©mentaire de la deuxiĂšme requĂȘte.
Y.
Yves Jacolin, bénévole de l'association GeoRezo.net, agit au nom et pour le compte de l'association - Partageons ce qui nous départage !! - GeoRezo vous aide ? Aidez GeoRezo !
Hors ligne
#3 Thu 01 September 2011 16:38
- tr
- Participant occasionnel
- Date d'inscription: 12 Jul 2011
- Messages: 25
Re: Optimisation de requĂȘte PostGIS
Bonjour,
Effectivement comme le dit Yves, l'opĂ©rateur && et la fonction st_intersects ne font pas la mĂȘme chose. Les docs de la version 1.5 sont ici :
- http://postgis.refractions.net/document … erlap.html
- http://postgis.refractions.net/document … sects.html
Selon la version de postgis, st_intersects ne fait pas de comparaison d'enveloppe il me semble. Il peut alors ĂȘtre utile dans le where de faire d'abord un "&&" puis un "st_intersects".
Et pour optimiser encore un peu, tu peux tester aussi en mettant
Code:
WHERE zone_humide='670057' AND zone_humide.the_geom && parcelle.the_geom AND Intersects(zone_humide.the_geom ,parcelle.the_geom)
Hors ligne
#4 Thu 01 September 2011 16:52
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Bon j'ai effectivement des indexes sur les données géographiques.
DĂšs mon retour au bureau je regardais les liens et essayera la requĂȘte proposĂ©e.
merci déjà pour ces infos.
Nebuka
Hors ligne
#5 Thu 01 September 2011 17:50
Re: Optimisation de requĂȘte PostGIS
Bonsoir,
dans mon souvenir,
Code:
st_intersects(geom1,geom2)
est la "nouvelle" syntaxe pour faire
Code:
geom1 && geom2 AND Intersects(geom1,geom2)
http://postgis.refractions.net/documentation/manual-1.5/ST_Intersects.html
mentionne "This function call will automatically include a bounding box comparison that will make use of any indexes that are available on the geometries."
Dernière modification par Mathieu BOSSAERT (Thu 01 September 2011 18:15)
Mathieu BOSSAERT
Association GeoRezo
Hors ligne
#6 Fri 02 September 2011 09:23
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Bonjour,
alors voilĂ les premiers tests de ce matin, donc avec la requĂȘte suivante :
Code:
SELECT idparcelle FROM parcelle, zone_humide WHERE zone_humide.the_geom && parcelle.the_geom AND Intersects(zone_humide.the_geom ,parcelle.the_geom) AND zone_humide='670057'
J'arrive Ă avoir un rĂ©sultat en un peu moins de 6 secondes, je vais lancer la requĂȘte sur une sĂ©lection d'une centaine de zone pour voir la durĂ©e de traitement.
Déjà un grand merci pour vos aide.
Nebuka
Hors ligne
#7 Fri 02 September 2011 09:42
Re: Optimisation de requĂȘte PostGIS
Pour Mathieu :
Je peux me tromper mais :
A && B
The "&&" operator is the "overlaps" operator. If A's bounding box overlaps B's bounding box the operator returns true.
Avant l'arrivé des fonctions st_* le fonctionnement était en effet d'utiliser cet opérateur non pas pour utiliser les index mais parce que cet opérateur déclenchait l'utilisation des index. Bon la nuance est faible, je vous l'accorde et je ne suis pas trÚs claire mais l'idée est que cet opérateur va réaliser un premier tri entre les géométries pour réaliser ensuite le test d'intersection qui va utiliser l'index.
Nebuka, si tu enlĂšves " zone_humide.the_geom && parcelle.the_geom AND " ta requĂȘte met combien de temps pour se rĂ©aliser ?
Y.
Yves Jacolin, bénévole de l'association GeoRezo.net, agit au nom et pour le compte de l'association - Partageons ce qui nous départage !! - GeoRezo vous aide ? Aidez GeoRezo !
Hors ligne
#8 Fri 02 September 2011 09:43
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
sans le && j'attend environ 2h20 avant d'avoir le résultat.
Hors ligne
#9 Fri 02 September 2011 12:12
- ChristopheV
- Membre
- Lieu: Ajaccio
- Date d'inscription: 7 Sep 2005
- Messages: 3235
- Site web
Re: Optimisation de requĂȘte PostGIS
Bonjour,
Quelle est la diffĂ©rence de traitement entre une requĂȘte utilisant && pour comparer les boxs et stocker le rĂ©sultat dans une table temporaire puis executer une requĂȘte intersect sur cette table temporaire et une requĂȘte comme indiquĂ©e par nebuka, qui combine les deux en une seule commande SQl ?
Ensuite juste pour info connaissez vous le type d'algo en Ćuvre dans intersects() ?
Christophe
L'avantage d'ĂȘtre une Ăźle c'est d'ĂȘtre une terre topologiquement close
Hors ligne
#10 Fri 02 September 2011 12:14
- Nicolas Granier
- Participant assidu
- Date d'inscription: 19 Apr 2007
- Messages: 271
Re: Optimisation de requĂȘte PostGIS
pour savoir si les index sont utilisĂ©s en fonction des diffĂ©rentes combinaisons (&& + Intersects, ST_intersects, && + ST_intersect,...), la fonction Explain peut ĂȘtre utilisĂ©e en prĂ©fixe de la requĂȘte.
A+
Hors ligne
#11 Fri 02 September 2011 13:18
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Bon alors aprĂšs quelques dizaines de minutes de traitement j'ai ce message d'erreur :
Code:
NOTICE: TopologyException: side location conflict at 924854 6.51993e+06 ERREUR: GEOS intersects() threw an error! ********** Erreur ********** ERREUR: GEOS intersects() threw an error! Ătat SQL :XX000
Donc pour débugger je fais un
Code:
SELECT isValid(the_geom) from zone_humide
et j'obtien 3 warning :
Code:
NOTICE: Ring Self-intersection at or near point 735616 7.04323e+06 NOTICE: Ring Self-intersection at or near point 955606 6.75697e+06 NOTICE: Ring Self-intersection at or near point 163887 6.77441e+06
J'ai corrigé les erreurs et je relance ... wait and see
Nebuka
Hors ligne
#12 Mon 05 September 2011 09:41
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Bon en fait ça fait presque 3 jours que ça corrige ma table parcelle ... je patiente encore.
Hors ligne
#13 Mon 05 September 2011 10:11
- ppluvinet
- Participant assidu
- Lieu: VALENCE
- Date d'inscription: 6 Aug 2007
- Messages: 628
Re: Optimisation de requĂȘte PostGIS
Plusieurs questions :
- Que fais-tu comme correction pour enlever les self-intersection ? Buffer(the_geom,0), cleangeometry(the_geom) ? voir http://www.kappasys.ch/pgtools/cleangeo … ometry.sql
- Es-tu sûr que les objets sont bien indexés ? Create index.... puis vacuum analyse. voir http://www.postgis.fr/node/187
- combien as-tu de parcelles ? combien as-tu de zones humides ? et quelle est en gros la surface moyenne d'une zone humide ?
- As tu tentĂ© de booster Postresql en de modifiant les paramĂštres par dĂ©faut de postgresql dans le fichier : C:\Program Files (x86)\PostgreSQL\8.4\data\postgresql.conf voir http://wiki.postgresql.org/wiki/Tuning_ … SQL_Server
A bientĂŽt
Pascal PLUVINET
Hors ligne
#14 Mon 05 September 2011 11:30
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Alors voici les réponse :
- Que fais-tu comme correction pour enlever les self-intersection ? Buffer(the_geom,0), cleangeometry(the_geom) ? voir http://www.kappasys.ch/pgtools/cleangeo ⊠ometry.sql
Pour enlever les self-intersection je fais un Buffer(the_geom,0) "BĂȘte et mĂ©chant" dans un Update ... le script donnĂ© en lien irait-il plus vite ?
- Es-tu sûr que les objets sont bien indexés ? Create index.... puis vacuum analyse. voir http://www.postgis.fr/node/187
Les indexes sont bien lĂ ... et par contre effectivement je n'ai pas fait de VACUUM ANALYSE ...
- combien as-tu de parcelles ? combien as-tu de zones humides ? et quelle est en gros la surface moyenne d'une zone humide ?
J'ai 50 000 000 de parcelle dans la base, 1 500 zones humide (surface moyenne ?)
- As tu tenté de booster Postresql en de modifiant les paramÚtres par défaut de postgresql dans le fichier : C:\Program Files (x86)\PostgreSQL\8.4\data\postgresql.conf voir http://wiki.postgresql.org/wiki/Tuning_ ⊠SQL_Server
Je suis sous CentOS pour PostGIS et j'ai modifié les lignes suivante lors de l'installation (postgresql.conf) :
shared_buffer=4GB (le serveur Ă 16Go de RAM)
work_mem=1GB
et c'est tout. Je ne maitrise pas spécialement le tuning, donc je n'ai touché à rien.
Si j'arrĂȘte le traitement "Buffer" qui tourne actuellement et que je fais un VACCUM ANALYSE est-ce que je peut gagner du temps de traitement ? et Ă©ventuellement utiliser le script ?
Hors ligne
#15 Mon 05 September 2011 13:23
Re: Optimisation de requĂȘte PostGIS
Alors voici les réponse :
- Que fais-tu comme correction pour enlever les self-intersection ? Buffer(the_geom,0), cleangeometry(the_geom) ? voir http://www.kappasys.ch/pgtools/cleangeo ⊠ometry.sql
Pour enlever les self-intersection je fais un Buffer(the_geom,0) "BĂȘte et mĂ©chant" dans un Update ... le script donnĂ© en lien irait-il plus vite ?
Pour mettre à jour une table entiÚre de 50M d'enregistrement, notamment s'il y a des géométries, il vaut mieux faire une création de nouvelle table avec tous les champs et la géométrie modifiée, puis supprimer l'ancienne et renommer la nouvelle. Ensuite rajouter les contraintes et les indexes.
Les updates de table entiÚre ça peut etre trÚs long, et ça nécessite ensuite de faire du vacuum, alors que la création de table élimine pas mal de problÚmes liés au MVCC.
D'autre part, si la machine est multi-processeur, il peut ĂȘtre intĂ©ressant de sĂ©parer la requĂȘte unique (qui va s'exĂ©cuter sur un seul processeur), en N requĂȘtes en parallĂšle, car l'opĂ©ration de buffer − st_buffer − est couteuse en calculs.
Mais le plus efficace reste de faire le st_buffer uniquement sur les géométries invalides, avec un update s'il n'y en a pas trop :
update parcelles set the_geom = st_buffer(the_geom, 0) where not st_isvalid(the_geom)
Hors ligne
#16 Mon 05 September 2011 13:25
- ppluvinet
- Participant assidu
- Lieu: VALENCE
- Date d'inscription: 6 Aug 2007
- Messages: 628
Re: Optimisation de requĂȘte PostGIS
Vincent a Ă©tĂ© un peu + rapide, je crois qu'on dit Ă peu prĂšs la mĂȘme chose dit autrement !
MĂȘme pour 50 000 000 de parcelles, je trouve que 3 jours c'est un peu beaucoup. Quelques heures me semblerait + raisonnable !
Pour optimiser la suppression des slf-intersection : j'opterais pour la fonction cleangeometry (qui fait bien + qu'enlever les self-intersection) et je mettrai une condition de type "where isValid(the_geom) = FALSE". De plus, pour optimiser le temps (mais pas la place sur le serveur !) je ne ferais pas un Update mais un select (il me semble que c'est beaucoup + rapide).
De plus, avec ce nombre important de parcelles et de zones humides, il semble indispensable d'utiliser les INDEX.
Code:
--- pour nettoyer : create table parcelle2 as select id_parcelle , the_geom from parcelle where isvalid(the_geom) union select id_parcelle ,cleangeometry( the_geom) as the_geom from parcelle where isvalid(the_geom) = FALSE; CREATE INDEX idx_parcelle2_gist ON parcelle2 USING GIST ( the_geom GIST_GEOMETRY_OPS ); --vacuum analyse indispensable si tu veux utiliser les index : vacuum analyse parcelle2 ;
Pour le tunning, il me semble qu'il y a d'autres choses Ă modifier comme effective_cache_size et maintainance_work_mem.
Ensuite pour la requette d'intersection , utilise ST_INTERSECTS()
Dernière modification par ppluvinet (Mon 05 September 2011 13:28)
Pascal PLUVINET
Hors ligne
#17 Mon 05 September 2011 14:53
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Merci pour vos info ppluvinet et vincentp la rĂ©paration Ă Ă©tĂ© effectivement plus rapide ... la j'ai en cours le vacuum analyse et aprĂšs je lance quelques requĂȘtes de test.
Si tout est OK je lance la requete principale.
Hors ligne
#18 Mon 05 September 2011 14:58
Re: Optimisation de requĂȘte PostGIS
Bonjour Pascal,
la fonction marche en effet trÚs bien! Par contre elle réalise déjà le test de validité.
Code:
[...] -- Only process if geometry is not valid, -- otherwise put out without change [...]
Un select simple sans union doit suffire.
Penser à recréer les contraintes sur la colonne the_geom.
Mathieu BOSSAERT
Association GeoRezo
Hors ligne
#19 Mon 05 September 2011 15:10
- tr
- Participant occasionnel
- Date d'inscription: 12 Jul 2011
- Messages: 25
Re: Optimisation de requĂȘte PostGIS
Dans postgis 1.5, "REINDEX TABLE" ne prennent pas en compte les index spatiaux (au lieu de faire un VACUUM ANALYSE) ?
Hors ligne
#20 Mon 05 September 2011 15:10
- ppluvinet
- Participant assidu
- Lieu: VALENCE
- Date d'inscription: 6 Aug 2007
- Messages: 628
Re: Optimisation de requĂȘte PostGIS
Salut Mathieu,
effectivement, le UNION n'est peut-ĂȘtre pas nĂ©cessaire si on utilise cleangeometry().
Pour optimiser la durée du vacuum analyse, il me semble qu'il faut augmenter la valeur par défault de maintainance_work_mem dans postgresql.conf (dans la limite du raisonnable bien sûr ! 300 Mo semble suffisant ). Il faut relancer le service ensuite.
Dernière modification par ppluvinet (Mon 05 September 2011 15:17)
Pascal PLUVINET
Hors ligne
#21 Mon 05 September 2011 15:54
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Bon apparemment j'aurais toujours des erreurs dans mes données "parcelle".
Quand j'ai utilisĂ© la requĂȘte de ppluvinet j'ai eu ça comme message :
Code:
NOTICE: Self-intersection at or near point 642276 6.87328e+06 CONTEXT: PL/pgSQL function "cleangeometry" line 15 at IF
pour moi je pensais qu'il avait corrigé les erreurs nan ? Ou est-ce que j'ai un soucis avec la fonction cleangeometry ?
Hors ligne
#22 Mon 05 September 2011 16:08
- ppluvinet
- Participant assidu
- Lieu: VALENCE
- Date d'inscription: 6 Aug 2007
- Messages: 628
Re: Optimisation de requĂȘte PostGIS
Je pense qu'il n'y a pas d'erreur, juste que POSTGIS a repéré une erreur et l'a corrigée.
Pour savoir s'il y a encore des erreurs, faire
Code:
select count(*) from parcelle2 where isvalid(the_geom) = FALSE ;
Si il trouve 0, alors c'est que les erreurs ont selble-t-il étaient corrigées.
Dernière modification par ppluvinet (Mon 05 September 2011 16:08)
Pascal PLUVINET
Hors ligne
#23 Wed 14 September 2011 13:36
- nebuka
- Participant occasionnel
- Date d'inscription: 1 Sep 2011
- Messages: 10
Re: Optimisation de requĂȘte PostGIS
Bonjour,
je viens aprÚs quelques jours d'absence vous donner les "résultats" des manipulations :
- tout d'abord j'ai réussis à corriger toutes les données géographique
- j'ai pu faire tourner ma "grosses" requĂȘte ... 2.5 jours de calcul et avoir tout les rĂ©sultats.
Au sujet de l'optimisation de la base, j'avais dĂ©jĂ fait toutes les manipulations dĂ©crites, par contre j'ai une question au sujet du multi processeurs. A priori postgres peut travailler en mutli processeurs mais 1 requĂȘtes par processeurs.
Est-ce qu'il n'y a pas moyen d'optimiser ça au niveau des fonctions spatiales ? Car en vérifiant les processus tournant sur mon serveur (top sous centos), j'ai vu que trÚs rarement il y avait 2 processus psql ... mais jamais 3 ou 4 (4 étant le nombre de core du serveur).
Encore merci pour vos différentes interventions qui on pu faire avancer le schmilblik.
Hors ligne
#24 Wed 14 September 2011 16:18
- Nicolas Ribot
- Membre
- Lieu: Toulouse
- Date d'inscription: 9 Sep 2005
- Messages: 1566
Re: Optimisation de requĂȘte PostGIS
Bonjour,
je viens aprÚs quelques jours d'absence vous donner les "résultats" des manipulations :
- tout d'abord j'ai réussis à corriger toutes les données géographique
- j'ai pu faire tourner ma "grosses" requĂȘte ... 2.5 jours de calcul et avoir tout les rĂ©sultats.
Au sujet de l'optimisation de la base, j'avais dĂ©jĂ fait toutes les manipulations dĂ©crites, par contre j'ai une question au sujet du multi processeurs. A priori postgres peut travailler en mutli processeurs mais 1 requĂȘtes par processeurs.
Est-ce qu'il n'y a pas moyen d'optimiser ça au niveau des fonctions spatiales ? Car en vérifiant les processus tournant sur mon serveur (top sous centos), j'ai vu que trÚs rarement il y avait 2 processus psql ... mais jamais 3 ou 4 (4 étant le nombre de core du serveur).
Encore merci pour vos différentes interventions qui on pu faire avancer le schmilblik.
Bonjour,
Postgresql n'est effectivement pas multithread: 1 requete ne peut tourner que sur un processeur.
Par contre, s'il y a plusieurs requetes, elles seront distribuées sur les differents processeurs de la machine.
Pour en profiter, une idee est de découper ses données spatialement (ou sur un autre critere) en autant de parties qu'il y a de processeurs, puis de lancer autant de requetes que de parties, pour tirer partie des différents processeurs.
A la fin du traitement, on reconstruit l'ensemble complet.
Nicolas
Hors ligne

