sql >> Databasteknik >  >> RDS >> PostgreSQL

Fråga efter koordinater tar för lång tid - alternativ att optimera?

Du kommer att bli mycket bättre av att använda ett rumsligt index som använder ett R-träd (i huvudsak ett tvådimensionellt index, som fungerar genom att dela upp utrymmet i rutor) och kommer att prestera mycket bättre än större än, mindre än jämförelser på två separata lat. , lon-värden på den här typen av fråga. Du måste dock skapa en geometrityp först, som du sedan indexerar och använder i din fråga istället för de separata lat/lon-par som du använder för närvarande.

Följande kommer att skapa en geometrityp, fylla i den och lägga till ett index till den, vilket säkerställer att det är en punkt och i lat/lon, känd som 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);

Sedan kan du köra följande fråga för att få dina händelser, som kommer att använda en spatial skärning, som bör använda ditt rumsliga index:

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;

Du skapar begränsningsrutan för din korsning genom att använda ST_MakeBOX2D med två uppsättningar punkter, som kommer att vara i diagonala hörn av begränsningsrutan, så SW och NE eller NW och SE-paren skulle båda fungera.

När du kör förklara på detta bör du se att det rumsliga indexet ingår. Detta kommer att fungera mycket bättre än två separata index på lon- och lat-kolumner, eftersom du bara träffar en indexerad, optimerad för rumslig sökning, snarare än två B-träd. Jag inser att detta representerar ett annat sätt att göra det och inte svarar på din ursprungliga fråga, förutom indirekt.

EDIT: Mike T har gjort den mycket goda poängen att för sökningar med begränsningsruta i 4326 är det mer lämpligt och snabbare att använda en geometridatatyp och &&-operatorn eftersom SRID ändå kommer att ignoreras, t.ex.

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



  1. Ta bort rader från flera tabeller i MySQL

  2. SQL Server:+(unär) operator på icke-numeriska strängar

  3. Flera rangordnar i en tabell

  4. sqlalchemy, ställer in MySQL-teckenuppsättningen som `create_engine`-argument