PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

La requête par coordonnées prend trop de temps - des options à optimiser ?

Vous ferez bien mieux d'utiliser un index spatial qui utilise un arbre R (essentiellement un index bidimensionnel, qui fonctionne en divisant l'espace en cases), et fonctionnera bien mieux que supérieur à, inférieur à des comparaisons sur deux lat distincts. , valeurs lon sur ce type de requête. Cependant, vous devrez d'abord créer un type de géométrie, que vous indexerez ensuite et utiliserez dans votre requête au lieu des paires lat/lon séparées que vous utilisez actuellement.

Ce qui suit créera un type de géométrie, le remplira et y ajoutera un index, en s'assurant qu'il s'agit d'un point et en lat/lon, appelé EPSG:4326

alter table event add column geom geometry(POINT, 4326);
update event set geom=ST_SetSrid(ST_MakePoint(lon, lat), 4326);
create index ix_spatial_event_geom on event using gist(geom);

Ensuite, vous pouvez exécuter la requête suivante pour obtenir vos événements, qui utiliseront une intersection spatiale, qui devrait utiliser votre index spatial :

Select * from events where ST_Intersects(ST_SetSRID(ST_MakeBox2D(ST_MakePoint(swLon, swLat), 
    ST_MakePoint(neLon, neLat)),4326), geom) 
order by relevancy desc limit 100;

Vous créez la boîte englobante pour votre intersection en utilisant ST_MakeBOX2D avec deux ensembles de points, qui seront sur les coins diagonaux de la boîte englobante, de sorte que les paires SW et NE ou NW et SE fonctionneraient toutes les deux.

Lorsque vous exécutez l'explication sur ceci, vous devriez constater que l'index spatial est inclus. Cela fonctionnera bien mieux que deux index séparés sur les colonnes lon et lat, car vous n'en touchez qu'un indexé, optimisé pour la recherche spatiale, plutôt que deux arbres B. Je me rends compte que cela représente une autre façon de procéder et ne répond pas à votre question initiale, sauf indirectement.

MODIF : Mike T a fait remarquer que pour les recherches de boîte englobante dans 4326, il est plus approprié et plus rapide d'utiliser un type de données géométrique et l'opérateur &&car le SRID sera de toute façon ignoré, par exemple,

 where ST_MakeBox2D(ST_MakePoint(swLon, swLat), ST_MakePoint(neLon, neLat)) && geom