How to create a spatial index on a PostgreSQL GEOMETRY field?

Viewed 2726

I am using PostgreSQL and PostGIS to handle geocoordinates in a table. How to create a spatial index on the GEOMETRY(POINT) type field to increase the performance of the distance-based ST_DWithin query?

I am using migrations to create indexes.

1 Answers

For geometry it is recommended to use a gist index, e.g.

CREATE INDEX idx_any_label ON mytable USING gist (geom_column);

Data sample (50k random points):

CREATE TABLE t (geom geometry(point,4326));
INSERT INTO t 
SELECT ('SRID=4326;POINT('||floor(random() * 50)||' ' ||floor(random() * 50) ||')')
FROM generate_series(1,50000);

Query plan without an index:

EXPLAIN ANALYSE
SELECT * FROM t
WHERE ST_DWithin('SRID=4326;POINT(1 1)',geom,1);
    
 Seq Scan on t  (cost=0.00..1252068.48 rows=5 width=32) (actual time=122.091..144.137 rows=98 loops=1)
   Filter: st_dwithin('0101000020E6100000000000000000F03F000000000000F03F'::geometry, geom, '1'::double precision)
   Rows Removed by Filter: 49902
 Planning Time: 0.083 ms
 JIT:
   Functions: 2
   Options: Inlining true, Optimization true, Expressions true, Deforming true
   Timing: Generation 0.387 ms, Inlining 83.228 ms, Optimization 30.947 ms, Emission 7.626 ms, Total 122.187 ms
 Execution Time: 186.107 ms

Query plan with a gist index

CREATE INDEX idx_t_geom ON t USING gist (geom);

EXPLAIN ANALYSE
SELECT * FROM t
WHERE ST_DWithin('SRID=4326;POINT(1 1)',geom,1);
                                                           QUERY PLAN                                                           
--------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on t  (cost=4.98..2119.16 rows=5 width=32) (actual time=0.086..0.367 rows=98 loops=1)
   Filter: st_dwithin('0101000020E6100000000000000000F03F000000000000F03F'::geometry, geom, '1'::double precision)
   Rows Removed by Filter: 83
   Heap Blocks: exact=139
   ->  Bitmap Index Scan on idx_t_geom  (cost=0.00..4.98 rows=77 width=0) (actual time=0.063..0.064 rows=181 loops=1)
         Index Cond: (geom && st_expand('0101000020E6100000000000000000F03F000000000000F03F'::geometry, '1'::double precision))
 Planning Time: 0.291 ms
 Execution Time: 2.237 ms

Demo: db<>fiddle

Related