PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

La query per coordinate richiede troppo tempo:opzioni da ottimizzare?

Sarai molto meglio usando un indice spaziale che utilizza un R-tree (essenzialmente un indice bidimensionale, che opera dividendo lo spazio in riquadri) e funzionerà molto meglio di maggiore, meno di confronti su due lat separati , lon valori su questo tipo di query. Tuttavia, dovrai prima creare un tipo di geometria, che poi indicizzerai e utilizzerai nella tua query invece delle coppie lat/lon separate che stai attualmente utilizzando.

Quanto segue creerà un tipo di geometria, lo popolerà e vi aggiungerà un indice, assicurandosi che sia un punto e in lat/lon, noto come 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);

Quindi puoi eseguire la seguente query per ottenere i tuoi eventi, che utilizzerà un'intersezione spaziale, che dovrebbe utilizzare il tuo indice spaziale:

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;

Crea il riquadro di delimitazione per la tua intersezione utilizzando ST_MakeBOX2D con due serie di punti, che saranno sugli angoli diagonali del riquadro di delimitazione, quindi le coppie SW e NE o le coppie NW e SE funzionerebbero entrambe.

Quando esegui spiegare su questo, dovresti scoprire che l'indice spaziale è incluso. Questo funzionerà molto meglio di due indici separati su colonne lon e lat, poiché stai colpendo solo uno indicizzato, ottimizzato per la ricerca spaziale, piuttosto che due B-tree. Mi rendo conto che questo rappresenta un altro modo di farlo e non risponde alla tua domanda originale, se non indirettamente.

MODIFICA: Mike T ha sottolineato molto bene che per le ricerche nel riquadro di delimitazione in 4326, è più appropriato e più rapido utilizzare un tipo di dati geometrico e l'operatore &&poiché lo SRID verrà comunque ignorato, ad esempio,

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