[FR]Optimiser les requêtes PostGIS : guide pratique pour améliorer les performances


Les bases de données spatiales peuvent contenir des millions d’objets géographiques. Dans certains cas, une requête PostGIS peut prendre plusieurs secondes, voire plusieurs minutes.

Ce problème apparaît souvent lorsque :

  • les index spatiaux ne sont pas utilisés
  • les géométries sont complexes
  • les requêtes spatiales sont mal construites
  • ou les statistiques de la base ne sont pas à jour.

Dans cet article, nous allons voir les étapes classiques pour diagnostiquer et optimiser une requête PostGIS lente.



1. Commencer par analyser la requête

La première étape consiste à comprendre comment PostgreSQL exécute la requête.

Pour cela on utilise :

EXPLAIN ANALYZE

Exemple :

EXPLAIN ANALYZE
SELECT *
FROM routes r
JOIN communes c
ON ST_Intersects(r.geom, c.geom);

Cette commande permet de voir :

  • si un index spatial est utilisé
  • combien de lignes sont analysées
  • combien de temps prend chaque étape.

Si vous voyez :

Seq Scan

cela signifie que PostgreSQL parcourt toute la table.


2. Vérifier la présence d’index spatiaux

Les index sont essentiels pour les requêtes spatiales.

Un index spatial se crée généralement ainsi :

CREATE INDEX idx_routes_geom
ON routes
USING GIST (geom);

Les index permettent à PostgreSQL de réduire fortement le nombre de géométries à analyser.

Sans index spatial, les performances peuvent être catastrophiques.


3. Utiliser les opérateurs spatiaux indexés

Certaines fonctions PostGIS utilisent automatiquement les index.

Par exemple :

Mais il est souvent utile d’ajouter un filtre par bounding box :

geom && other_geom

Exemple :

SELECT *
FROM routes r
JOIN communes c
ON r.geom && c.geom
AND ST_Intersects(r.geom, c.geom);

Le test de bounding box est beaucoup plus rapide.


4. Vérifier la complexité des géométries

Les géométries très détaillées peuvent ralentir fortement certaines opérations.

Dans certains cas, il peut être utile de simplifier les géométries :

ST_Simplify(geom, tolerance)

ou de créer une table simplifiée pour certaines analyses.


5. Éviter certaines fonctions dans les clauses WHERE

Certaines fonctions empêchent l’utilisation des index.

Par exemple :

ST_Buffer(geom, 100)

dans une clause WHERE peut ralentir fortement la requête.

Mauvais exemple :

WHERE ST_Intersects(ST_Buffer(geom,100), zone)

Il est souvent préférable de reformuler la requête.


6. Vérifier les statistiques de la base

PostgreSQL utilise des statistiques pour choisir le plan d’exécution.

Après de nombreuses modifications de données, il est recommandé d’exécuter :

ANALYZE

ou

VACUUM ANALYZE

Cela permet d’améliorer le plan de requête.


7. Limiter les données analysées

Il est souvent utile de réduire le volume de données avant les opérations spatiales.

Par exemple avec un filtre attributaire :

WHERE type = 'autoroute'

Cela permet de réduire le nombre d’objets testés.


8. Tester différentes approches

Dans certains cas, plusieurs formulations de requêtes peuvent donner des performances très différentes.

Il est donc utile de tester différentes stratégies :

  • jointure spatiale
  • sous-requête
  • matérialisation intermédiaire.

9. Les 5 erreurs PostGIS les plus fréquentes qui ralentissent une requête

Certaines erreurs reviennent très souvent dans les bases de données spatiales.

Absence d’index spatial

C’est la cause la plus fréquente.

Sans index spatial, PostgreSQL doit analyser toutes les géométries de la table.

Créer un index :

CREATE INDEX idx_routes_geom
ON routes
USING GIST (geom);


Mauvais ordre des opérations

Certaines requêtes exécutent directement une opération spatiale coûteuse sur toute la table.

Exemple inefficace :

SELECT *
FROM batiments
WHERE ST_Intersects(geom, ST_Buffer(:zone,100));

Dans ce cas, la fonction ST_Buffer est recalculée pour chaque ligne.


Fonction spatiale utilisée sans filtre spatial

Une jointure spatiale peut être très lente si l’on n’utilise pas de filtre de bounding box.

Exemple recommandé :

SELECT *
FROM routes r
JOIN communes c
ON r.geom && c.geom
AND ST_Intersects(r.geom, c.geom);

Le test && utilise l’index spatial.


Géométries trop complexes

Certaines géométries contiennent des milliers de sommets.

Dans certains cas il peut être utile d’utiliser :

ST_Simplify(geom, tolerance)

ou de stocker une version simplifiée.


Statistiques PostgreSQL obsolètes

Si la table a été fortement modifiée, PostgreSQL peut choisir un mauvais plan d’exécution.

Mettre à jour les statistiques :

VACUUM ANALYZE


Exemple réel d’optimisation

Supposons une requête qui cherche les routes dans une commune.

Requête initiale :

SELECT r.*
FROM routes r, communes c
WHERE ST_Intersects(r.geom, c.geom)
AND c.nom = 'Paris';

Temps d’exécution : 45 secondes


Version optimisée

SELECT r.*
FROM routes r
JOIN communes c
ON r.geom && c.geom
AND ST_Intersects(r.geom, c.geom)
WHERE c.nom = 'Paris';

Avec :

  • index spatial
  • filtre bounding box

Temps d’exécution : moins d’une seconde


Checklist rapide pour diagnostiquer une requête PostGIS lente

Lorsqu’une requête prend trop de temps, vérifiez :

✔ la requête avec EXPLAIN ANALYZE
✔ la présence d’un index spatial
✔ l’utilisation des opérateurs compatibles avec les index
✔ la complexité des géométries
✔ la présence d’un filtre attributaire
✔ les statistiques PostgreSQL (ANALYZE)


Conclusion

Lorsqu’une requête PostGIS est lente, il est important de suivre une démarche progressive :

  1. analyser la requête avec EXPLAIN ANALYZE
  2. vérifier les index spatiaux
  3. utiliser les opérateurs compatibles avec les index
  4. simplifier les géométries si nécessaire
  5. maintenir les statistiques de la base.

Avec ces quelques étapes, il est souvent possible de réduire le temps d’exécution de plusieurs minutes à quelques secondes.

Dans la majorité des cas, une requête PostGIS lente est liée à un index manquant ou à un mauvais plan d’exécution. Une analyse méthodique avec EXPLAIN ANALYZE permet presque toujours d’identifier le problème.


Si cet article vous a intéressé et que vous pensez qu'il pourrait bénéficier à d'autres personnes, n'hésitez pas à le partager sur vos réseaux sociaux en utilisant les boutons ci-dessous. Votre partage est apprécié !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Are you human? Please solve:Captcha