Query by coordinates takes too long - options to optimize?

后端 未结 1 1286
情话喂你
情话喂你 2021-01-15 02:09

I have a table where I store events (about 5M at the moment, but there will be more). Each event has two attributes that I care about for this query - location

相关标签:
1条回答
  • 2021-01-15 02:40

    You will be much better off using a spatial index which uses an R-tree (essentially a two-dimensional index, which operates by dividing the space into boxes), and will perform far better than greater than, less than comparisons on two separate lat, lon values on this kind of query. You will need to create a geometry type first though, which you then index and use in your query instead of the separate lat/lon pairs you are currently using.

    The following will create a geometry type, populate it, and add an index to it, ensuring that it is a point and in lat/lon, known as 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);
    

    Then you can run the following query to get your events, which will use a spatial intersects, which should utilize your spatial 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;
    

    You make the bounding box for your intersection by using ST_MakeBOX2D with two sets of points, which will be on diagonal corners of the bounding box, so the SW and NE or the NW and SE pairs, would both work.

    When you run explain on this, you should find that the spatial index is included. This will perform vastly better than two separate indexes on lon and lat columns, as you are only hitting one indexed, optimized for spatial search, rather than two B-trees. I realize that this represents another way of doing it and does not answer you original question, except indirectly.

    EDIT: Mike T has made the very good point that for bounding box searches in 4326, it is more appropriate and quicker to use a geometry data type and the && operator as the SRID will be ignored anyway, eg,

     where ST_MakeBox2D(ST_MakePoint(swLon, swLat), ST_MakePoint(neLon, neLat)) && geom
    
    0 讨论(0)
提交回复
热议问题