Comment puis-je optimiser une requête Point dans le polygone pour des millions de points lorsque la plupart des points se trouvent dans le polygone?

8

J'ai 150 millions de points dans une table de points et je voudrais trouver les quelques points situés en dehors d'une géométrie polygonale donnée. Je sais que 99,9% des points sont dans la géométrie du polygone. Je suis intéressé à trouver les quelques points qui se trouvent en dehors du polygone.

Ma meilleure requête actuelle utilisant des tables PostGIS indexées prend environ 30 minutes. Existe-t-il un moyen d'optimiser la requête suivante en sachant que la plupart des points se trouvent dans le polygone (bordure)?

SELECT COUNT(*) 
FROM italy_points pt
JOIN borders poly
ON ST_WITHIN (pt.the_geom, poly.geom)
WHERE poly.iso3 = 'ITA'; 

Le polygone est essentiellement la frontière administrative de l'Italie. Sommets - 405 000. Pièces - 510. L'enveloppe est beaucoup plus grande que le polygone (le polygone couvre 24% de l'enveloppe)

Prithvi
la source
2
Veuillez modifier la question pour donner une indication de la complexité du polygone - Combien de pièces? Combien de sommets? Quel pourcentage de l'enveloppe du polygone se trouve dans le polygone. J'ai constaté que le partitionnement de polygones complexes peut améliorer l'évaluation de polygones ponctuels , mais vous devez gérer la condition dans laquelle un seul point intersecte plusieurs partitions.
Vince
La première optimisation pour ce type d'opération consiste généralement à vérifier si le point se trouve dans la zone de délimitation du polygone avant de passer à l'opération point à polygone complète. Le point-in-box est une opération très efficace en comparaison.
WhiteboxDev
@Vince Si des doublons sont possibles (le seul cas auquel je pense, c'est quand il tombe exactement à la frontière de deux partitions), cela est trivialement géré dans PostGIS. Vous n'avez besoin que de GROUP BYla clé primaire des points. (PostgreSQL vous permet de référencer commodément toutes les colonnes de la SELECTclause qui proviennent d'une table où la clé primaire est incluse dans la GROUP BYclause.)
jpmc26
@WhiteboxDev effectue ST_Withindéjà une vérification de la zone de délimitation qui permet d'utiliser l'index. (Presque toutes les fonctions de PostGIS incluent cette optimisation.) S'il est encore lent, le problème est clairement lié à la complexité du polygone.
jpmc26
@ jpmc26 Certainement, mais la requête SQL devrait également être modifiée pour être utilisée ST_Intersects, car ST_Withinelle ne correspondrait pas de manière fiable aux conditions aux limites internes.
Vince

Réponses:

10

Utilisez ST_Subdivide pour couper votre polygone en petits polygones, enregistrez-les dans une table et créez un index spatial. Faites ensuite votre requête sur les polygones maillés.

Sans cela, l'indexation spatiale ne présente aucun avantage dans votre cas (seulement 1 polygone d'intérêt).

Mesa
la source
4
Suite au commentaire ST_Subdivide (), vous pouvez constater que l'utilisation d'un nombre de sommets inférieur au nombre par défaut génère des gains supplémentaires en augmentant l'effet de levier d'index et en diminuant le temps de récupération de la géométrie. Essayez 64 ou même 32.
Paul Ramsey
La requête se termine maintenant en 5 minutes au lieu de 30! Merci pour la suggestion.
Prithvi
Wow, c'était un cri incroyablement bon. Ma requête faisait planter une machine avec 62 Go de RAM en moins de 2 minutes, puis ce ST_Subdivide l'a fait non seulement ne pas planter, mais s'exécuter en quelques secondes. Je viens de trouver mon nouveau meilleur ami!
Momchill