Je ne peux pas faire fonctionner PostGIS 2.1 sur PostgreSQL 9.3.5 pour utiliser un index spatial même pour les requêtes les plus simples. L' ensemble de données est de 8 millions de points (grille de dénombrement de la population d'ici) . Le tableau est créé en tant que
CREATE TABLE points (
population DOUBLE PRECISION NOT NULL,
location GEOGRAPHY(4326, POINT) NOT NULL
)
CREATE INDEX points_gix ON points USING GIST(location);
Les requêtes sont aussi simples que possible
SELECT SUM(population)
FROM points
WHERE ST_Distance(
location,
ST_GeographyFromText('SRID=4326; POINT(0 0)')
) < 1000
PostgreSQL utilise toujours le scan Seq pour cela, j'ai essayé un sous-ensemble avec 10000 points - toujours le scan Seq. Des idées?
Réponses:
ST_Distance calcule en fait la distance entre toutes les paires de points, donc, en tant que tel, aucun index n'a pu être utilisé. Votre requête effectuera donc un balayage de séquence, puis choisira les géométries qui sont inférieures à la distance que vous spécifiez. Vous recherchez ST_DWithin , qui utilise un index.
ST_Distance est plus utile pour classer les résultats, souvent conjointement avec ORDER BY et / ou LIMIT, qui ont été obtenus avec des requêtes qui utilisent un index.
la source
Comme l'a dit @ JohnPowellakaBarça,
ST_DWithin()
c'est la voie à suivre lorsque vous voulez être correct .Cependant, dans mon cas, je ne veux qu'une estimation approximative, donc même
ST_DWithin()
trop cher (en coût de requête) pour mes besoins. J'ai utilisé&&
etST_Expand(box2d)
(ne confondez pas cela avec lageometry
version) à la place. Exemple:Ce qui sera immédiatement évident, c'est que nous avons affaire à des degrés plutôt qu'à des mètres et à l'utilisation d'un cadre de délimitation au lieu d'un cercle dans un sphéroïde. Pour mon cas d'utilisation, cela passe de 24 ms à seulement 2 ms (localement en SSD). Cependant, pour ma base de données de production dans AWS RDS PostgreSQL avec des connexions simultanées et des quotas IOPS à peine généreux (100 IOPS), la
ST_DWithin()
requête d' origine dépense trop d'IOPS et peut s'exécuter plus de 2000 ms et bien pire lorsque le quota d'IOPS est épuisé.Ce n'est pas pour tout le monde mais au cas où vous pourriez sacrifier une certaine précision pour la vitesse (ou pour économiser les IOPS), alors cette approche pourrait être pour vous. Comme vous pouvez le voir dans les plans de requête ci-dessous,
ST_DWithin
nécessite toujours un filtre spatial à l'intérieur du Bitmap Heap Scan en plus de Recheck Cond, tandis que&&
sur une boîte, la géométrie n'a pas besoin de Filter et utilise uniquement Recheck Cond.J'ai également remarqué que
IS NOT NULL
ce qui compte, sans lui, vous vous retrouverez avec un pire plan de requête. Il semble que l'indice GIST ne soit pas "assez intelligent" pour cela. (bien sûr, ce n'est pas nécessaire si votre colonne estNOT NULL
, dans mon cas, c'estNULL
possible)Table de 20000 lignes,
ST_DWithin(geography, geography, 100000, FALSE)
sur AWS RDS 512 Mo de RAM avec 300 IOPS:Table de 20000 lignes
&&
etST_Expand(box2d)
sur AWS RDS 512 Mo de RAM avec 300 IOPS:Encore une fois avec une requête plus simple:
Table de 20000 lignes,
ST_DWithin(geography, geography, 100000, FALSE)
sur AWS RDS 512 Mo de RAM avec 300 IOPS:Table de 20000 lignes
&&
etST_Expand(box2d)
sur AWS RDS 512 Mo de RAM avec 300 IOPS:la source