Search code examples
postgresqlpostgis

ST_Intersects is too slow


I have table

CREATE TABLE BulkContainers 
( objectId int PRIMARY KEY NOT NULL,
  geometryType VARCHAR(10) NOT NULL, 
  geodata geometry NOT NULL, 
  timeFrom time, 
  timeTo time, 
  cityDistrict VARCHAR(25), 
  street VARCHAR(60),
  trashTypeName VARCHAR(20), 
  payer VARCHAR(40), 
  day date);

Table contains ~60k records, where geodata are only points.

I created gist index over geodata attribute.

Unfortunatelly, the queries are very slow. I have testing query collection, where I use ST_Intersects function and I am getting the throughput ~20q/s.

Example of queries:

SELECT * FROM BulkContainers WHERE ST_Intersects('POLYGON((14.435818094927747 50.117437918784645,14.435860110788347 50.100516737473654,14.436327451178308 50.105539453354766,14.43664241497306 50.100437942566366,14.437047791355718 50.11031766846078,14.437714063262893 50.105611788231904,14.439779334511888 50.11428054963237,14.438273887651917 50.119529142381225,14.43732995152818 50.11984052052608,14.435818094927747 50.117437918784645))', geodata) IS TRUE;

Index was created as:

CREATE INDEX iindex ON BulkContainers USING gist(geodata); 

Explain plan is as follows:

"QUERY PLAN"
"Seq Scan on public.bulkcontainers  (cost=0.00..3823.65 rows=20 width=124) (actual time=27.961..27.961 rows=0 loops=1)"
"  Output: objectid, geometrytype, geodata, timefrom, timeto, citydistrict, street, trashtypename, payer, day"
"  Filter: (((bulkcontainers.geodata && '010300000001000000040000001F85EB51B8DE2C40022B8716D90E4940AC1C5A643BDF2C4077BE9F1A2F0D4940C74B378941E02C40CDCCCCCCCC0C49401F85EB51B8DE2C40022B8716D90E4940'::geometry) AND _st_intersects(bulkcontainers.geodata, '010300000001000000040000001F85EB51B8DE2C40022B8716D90E4940AC1C5A643BDF2C4077BE9F1A2F0D4940C74B378941E02C40CDCCCCCCCC0C49401F85EB51B8DE2C40022B8716D90E4940'::geometry)) IS TRUE)"
"  Rows Removed by Filter: 67084"
"  Buffers: shared hit=1308"
"Planning time: 2.168 ms"
"Execution time: 28.207 ms"

Solution

  • The IS TRUE screws up the usage of the index. Just write the bare st_intersects function call. It means the same thing, but is written in a way which tickles the indexing machinery.

    I sometimes get this to fail to use the index even without the IS TRUE, but that is not reproducible. I think it occurs when I have a bastardized installation, where PostgreSQL was recompiled and installed over the top of a previous installation, but postgis was not also recompiled and reinstalled. So there is a header mismatch.