[postgis-users] Why is my PostGIS query not using a spatial index?
Kevin Tran
hekevintran at gmail.com
Tue Aug 30 02:58:36 PDT 2011
I am having an issue with a spatial query that is not making use of indexes.
My schema is:
CREATE TABLE geoplanet_place
(
woeid integer NOT NULL,
"name" character varying(300) NOT NULL,
admin_1 character varying(300),
coords geometry NOT NULL,
bbox geometry NOT NULL,
CONSTRAINT geoplanet_place_pkey PRIMARY KEY (woeid),
CONSTRAINT enforce_dims_bbox CHECK (st_ndims(bbox) = 2),
CONSTRAINT enforce_dims_coords CHECK (st_ndims(coords) = 2),
CONSTRAINT enforce_geotype_bbox CHECK (geometrytype(bbox) = 'POLYGON'::text OR bbox IS NULL),
CONSTRAINT enforce_geotype_coords CHECK (geometrytype(coords) = 'POINT'::text OR coords IS NULL),
CONSTRAINT enforce_srid_bbox CHECK (st_srid(bbox) = 4326),
CONSTRAINT enforce_srid_coords CHECK (st_srid(coords) = 4326)
)
WITH (
OIDS=FALSE
);
My indexes are:
CREATE INDEX geoplanet_place_bbox_id
ON geoplanet_place
USING gist
(bbox);
CREATE INDEX geoplanet_place_coords_id
ON geoplanet_place
USING gist
(coords);
Query A:
SELECT "geoplanet_place"."woeid", "geoplanet_place"."name", "geoplanet_place"."admin_1"
FROM "geoplanet_place"
WHERE "geoplanet_place"."bbox" && ST_Expand(ST_GeomFromText('POINT (-71.4119869999999963 41.8238720000000015)', 4326), 16093.44)
AND ST_distance_sphere("geoplanet_place"."coords", ST_GeomFromText('POINT (-71.4119869999999963 41.8238720000000015)', 4326)) <= 16093.44
ORDER BY "geoplanet_place"."woeid" ASC
LIMIT 5;
Running EXPLAIN ANALYZE on Query A yields:
Limit (cost=0.00..56.00 rows=5 width=24) (actual time=1440.482..1451.604 rows=5 loops=1)
-> Index Scan using geoplanet_place_pkey on geoplanet_place (cost=0.00..20018585.21 rows=1787420 width=24) (actual time=1440.477..1451.583 rows=5 loops=1)
Filter: ((bbox && '0103000020E61000000100000005000000CFF6E80D6D92CFC0134548DDCE59CFC0CFF6E80D6D92CFC02BC58EC6A183CF406F13EE95034BCF402BC58EC6A183CF406F13EE95034BCF40134548DDCE59CFC0CFF6E80D6D92CFC0134548DDCE59CFC0'::geometry) AND (st_distance_sphere(coords, '0101000020E610000023D8B8FE5DDA51C0890B40A374E94440'::geometry) <= 16093.44::double precision))
Total runtime: 1451.657 ms
(4 rows)
I guess the plan is using the index because the query completes quickly, but it doesn't mention the index anywhere.
---
Query B is Query A rewritten to use ST_DWithin(). This function call is supposed to be equivalent to Query A's WHERE clause.
Query B:
SELECT "geoplanet_place"."woeid", "geoplanet_place"."name", "geoplanet_place"."admin_1"
FROM "geoplanet_place"
WHERE ST_DWithin("geoplanet_place"."bbox", ST_GeomFromText('POINT (-71.4119869999999963 41.8238720000000015)', 4326), 16093.44)
ORDER BY "geoplanet_place"."woeid" ASC
LIMIT 5;
Running EXPLAIN on Query B yields:
Limit (cost=1884535.96..1884535.97 rows=5 width=24)
-> Sort (cost=1884535.96..1884535.98 rows=9 width=24)
Sort Key: woeid
-> Seq Scan on geoplanet_place (cost=0.00..1884535.82 rows=9 width=24)
Filter: ((bbox && '0103000020E61000000100000005000000CFF6E80D6D92CFC0134548DDCE59CFC0CFF6E80D6D92CFC02BC58EC6A183CF406F13EE95034BCF402BC58EC6A183CF406F13EE95034BCF40134548DDCE59CFC0CFF6E80D6D92CFC0134548DDCE59CFC0'::geometry) AND ('0101000020E610000023D8B8FE5DDA51C0890B40A374E94440'::geometry && st_expand(bbox, 16093.44::double precision)) AND _st_dwithin(bbox, '0101000020E610000023D8B8FE5DDA51C0890B40A374E94440'::geometry, 16093.44::double precision))
(5 rows)
I didn't allow EXPLAIN ANALYZE on Query B to finish because it was taking a long time.
I ran ANALYZE to see if it would help, but nothing changed:
ANALYZE VERBOSE geoplanet_place (bbox, coords);
Questions:
1. Why does the result of EXPLAIN on Query A not say anything about indexes?
2. Why does Query B result in a different query plan when it should be equivalent to Query A?
3. What must I do so that Query B will be fast?
4. Is there a problem with my indexes? Will changing the statistics on the geometry columns change anything?
Links:
1. Building Indexes for PostGIS: http://postgis.refractions.net/documentation/manual-svn/using_postgis_dbmanagement.html#id2757356
2. ST_DWithin: http://postgis.refractions.net/documentation/manual-svn/ST_DWithin.html
3. Statistics Used by the Planner: http://www.postgresql.org/docs/8.4/interactive/planner-stats.html
More information about the postgis-users
mailing list