Я пытаюсь улучшить производительность для запроса ниже. Независимо от того, как я пишу запрос (подзапрос в предложении FROM, подзапрос в предложении WHERE) postgres настаивает на запуске всех ~ 570K строк через дорогую функцию ST_DWITHIN, даже если есть только 60 строк, в которых county = 24. Как я могу заставить postgres фильтровать на county = 24 ПЕРЕД выполнением функции postgis, которая, как мне кажется, будет намного быстрее и намного эффективнее? 700 мс не является причиной для слишком большого беспокойства, но поскольку эта таблица увеличивается до 10 М +, я беспокоюсь о производительности.
Также следует отметить, что p.id - это первичный ключ, p.zipcode - это индекс fk, z.county - это индекс fk, а p.geom имеет индекс GiST.
Запрос:
EXPLAIN ANALYZE
SELECT count(p.id)
FROM point AS p
LEFT JOIN zipcode AS z
ON p.zipcode = z.zipcode
WHERE z.county = 24
AND ST_DWithin(
p.geom,
ST_SetSRID(ST_Point(-121.479756008715,38.563236291512),4269),
16090.0,
false
)
ОБЪЯСНИТЬ АНАЛИЗ:
Aggregate (cost=250851.91..250851.92 rows=1 width=4) (actual time=724.007..724.007 rows=1 loops=1)
-> Hash Join (cost=152.05..250851.34 rows=228 width=4) (actual time=0.359..723.996 rows=51 loops=1)
Hash Cond: ((p.zipcode)::text = (z.zipcode)::text)
-> Seq Scan on point p (cost=0.00..250669.12 rows=7437 width=10) (actual time=0.258..723.867 rows=63 loops=1)
Filter: (((geom)::geography && '0101000020AD10000063DF8B52B45E5EC070FB752018484340'::geography) AND ('0101000020AD10000063DF8B52B45E5EC070FB752018484340'::geography && _st_expand((geom)::geography, 16090::double precision)) AND _st_dwithin((g (...)
Rows Removed by Filter: 557731
-> Hash (cost=151.38..151.38 rows=54 width=6) (actual time=0.095..0.095 rows=54 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 3kB
-> Bitmap Heap Scan on zipcode z (cost=4.70..151.38 rows=54 width=6) (actual time=0.023..0.079 rows=54 loops=1)
Recheck Cond: (county = 24)
Heap Blocks: exact=39
-> Bitmap Index Scan on fki_zipcode_county_foreign_key (cost=0.00..4.68 rows=54 width=0) (actual time=0.016..0.016 rows=54 loops=1)
Index Cond: (county = 24)
Planning time: 0.504 ms
Execution time: 724.064 ms
point
копирую ~ 60 строк, в которых county = 24, в новую таблицу, запрос занимает всего 0,403 мс по сравнению с 724, поэтому, безусловно, есть большая разница.
count(*)
как вопрос стиля. Если id
это pkid, как вы говорите, это NOT NULL
означает, что они одинаковы. За исключением count(id)
того недостатка, что вы должны задать этот вопрос, если id
обнуляется.