У меня есть такая таблица:
CREATE TABLE products (
id INT,
latitude numeric(9,6),
longitude numeric(9,6),
is_location_independent boolean
);
INSERT INTO products (id, latitude, longitude, is_location_independent) VALUES (1, 56.1508469,10.2128301,false);
INSERT INTO products (id, latitude, longitude, is_location_independent) VALUES (2,56.1508469,15.2128301,true);
Я хочу создать индекс, который эффективно охватывает следующий запрос:
SELECT COUNT(*) FROM products
WHERE
(ST_DWithin( ST_GeographyFromText( 'SRID=4326;POINT(' || longitude || ' ' || latitude || ')' ), ST_GeographyFromText('SRID=4326;POINT(13.621700 45.940900)'), 80000 ) OR is_location_independent IS TRUE)
Я пытался создать:
CREATE INDEX CONCURRENTLY index_products_location
ON products USING gist
(st_geographyfromtext(((('SRID=4326;POINT('::text || longitude) || ' '::text) || latitude) || ')'::text), is_location_independent)
TABLESPACE pg_default;
Но я получаю следующее исключение:
ERROR: data type boolean has no default operator class for access method "gist"
Теперь индекс без комбинации с is_location_independent
не будет работать хорошо. Без этого планировщик запросов решает выполнить последовательное сканирование таблицы, и в ней миллионы строк, поэтому он работает медленно (8 se c).
Что я могу сделать?
PS: Postgresql 11
Обновление
После добавления следующих двух индексов:
CREATE INDEX ON products USING gist (
st_geographyfromtext(
'SRID=4326;POINT(' || longitude || ' ' || latitude || ')'
)
) WHERE is_location_independent;
и
CREATE INDEX ON products USING btree (
is_location_independent
);
И имея такие данные, как: is_location_independent: true => 1493 записей и is_location_independent: false => 1 359 200
При выполнении запроса планировщик запросов фактически не использует индекс GEO, то есть тот, который было бы очень полезно для запроса ...
"Finalize Aggregate (cost=262104.14..262104.15 rows=1 width=8) (actual time=2297.030..2297.030 rows=1 loops=1)"
" -> Gather (cost=262103.72..262104.13 rows=4 width=8) (actual time=2292.063..2667.239 rows=5 loops=1)"
" Workers Planned: 4"
" Workers Launched: 4"
" -> Partial Aggregate (cost=261103.72..261103.73 rows=1 width=8) (actual time=2273.565..2273.566 rows=1 loops=5)"
" -> Parallel Index Scan using index_products_on_is_location_independent on products (cost=0.43..261093.34 rows=4152 width=0) (actual time=12.878..2272.703 rows=4461 loops=5)"
" Filter: (((st_geographyfromtext((((('SRID=4326;POINT('::text || (longitude)::text) || ' '::text) || (latitude)::text) || ')'::text)) && '0101000020E6100000AED85F764F3E2B40386744696FF84640'::geography) AND ('0101000020E6100000AED85F764F3E2B40386744696FF84640'::geography && _st_expand(st_geographyfromtext((((('SRID=4326;POINT('::text || (longitude)::text) || ' '::text) || (latitude)::text) || ')'::text)), '80000'::double precision)) AND _st_dwithin(st_geographyfromtext((((('SRID=4326;POINT('::text || (longitude)::text) || ' '::text) || (latitude)::text) || ')'::text)), '0101000020E6100000AED85F764F3E2B40386744696FF84640'::geography, '80000'::double precision, true)) OR (is_location_independent IS TRUE))"
" Rows Removed by Filter: 257706"
Так что, как вы можете видеть, индексация не работает эффективно ...