У меня есть две таблицы, products
и products_names
.Джин не используется на двух столбцах одновременно в JOIN
Я делаю ILIKE
в двух столбцах с индексом GIN в обеих таблицах, но GIN используется, только если я делаю ILIKE
только на одном столбце.
Я сделал обходным путем, выполнив UNION, но я хотел бы знать, почему он не работает, поскольку я думал, что он должен.
Обе колонны, n.name
и e.producer
являются VARCHAR имеют индекс GIN на них:
CREATE INDEX products_producer_gin_idx ON products USING gin (producer gin_trgm_ops);
CREATE INDEX products_names_name_gin_idx ON products_names USING gin (name gin_trgm_ops);
Выберите с помощью JOIN и ILIKE который не использует GIN:
testdb=# explain (analyze, verbose)
SELECT n.name, e.producer
FROM products e
INNER JOIN products_names n ON
n.product_id = e.product_id
WHERE
n.name ilike '%eda%' or e.producer ilike '%eda%'
limit 20;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.42..2725.92 rows=20 width=60) (actual time=0.582..62.658 rows=20 loops=1)
Output: n.name, e.producer
-> Nested Loop (cost=0.42..669928.73 rows=4916 width=60) (actual time=0.582..62.652 rows=20 loops=1)
Output: n.name, e.producer
-> Seq Scan on public.products e (cost=0.00..220800.16 rows=446716 width=29) (actual time=0.002..5.363 rows=17067 loops=1)
Output: e.producer, e.product_id
-> Index Scan using products_names_pkey on public.products_names n (cost=0.42..1.00 rows=1 width=39) (actual time=0.003..0.003 rows=0 loops=17067)
Output: n.product_id, n.lang, n.name, n.name2, n.name3, n.products
Index Cond: (n.product_id = e.product_id)
Filter: (((n.name)::text ~~* '%eda%'::text) OR ((e.producer)::text ~~* '%eda%'::text))
Rows Removed by Filter: 1
Planning time: 0.559 ms
Execution time: 62.677 ms
(13 Zeilen)
Zeit: 63,529 ms
SELECT на одном столбце n.name, которое использует GIN:
testdb=# explain (analyze, verbose)
SELECT n.name, e.producer
FROM products e
INNER JOIN products_names n ON
n.product_id = e.product_id
WHERE
n.name ilike '%eda%'
limit 20;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=58.34..260.70 rows=20 width=60) (actual time=0.257..0.458 rows=20 loops=1)
Output: n.name, e.producer
-> Nested Loop (cost=58.34..49564.37 rows=4893 width=60) (actual time=0.256..0.454 rows=20 loops=1)
Output: n.name, e.producer
-> Bitmap Heap Scan on public.products_names n (cost=57.92..14890.29 rows=4893 width=39) (actual time=0.245..0.333 rows=20 loops=1)
Output: n.product_id, n.lang, n.name, n.name2, n.name3, n.products
Recheck Cond: ((n.name)::text ~~* '%eda%'::text)
Heap Blocks: exact=18
-> Bitmap Index Scan on products_names_name_gin_idx (cost=0.00..56.70 rows=4893 width=0) (actual time=0.160..0.160 rows=797 loops=1)
Index Cond: ((n.name)::text ~~* '%eda%'::text)
-> Index Scan using products_pkey on public.products e (cost=0.42..7.08 rows=1 width=29) (actual time=0.005..0.006 rows=1 loops=20)
Output: e.producer, e.product_id
Index Cond: (e.product_id = n.product_id)
Planning time: 1.000 ms
Execution time: 0.494 ms
(15 Zeilen)
Zeit: 2,563 ms
Возможный дубликат [PostgreSQL LIKE изменений производительности запросов] (http://stackoverflow.com/questions/1566717/postgresql-like- query-performance-changes) – e4c5