Reputation: 212
I have a view that is composed from elements of various tables:
CREATE OR REPLACE VIEW public.search_view
AS SELECT search_data.key,
search_data.title,
search_data.content
FROM ( SELECT 'foo.'::text || foo.id AS key,
foo.name AS title,
foo.information AS content
FROM foo
UNION ALL
SELECT 'bar.'::text || bar.id AS key,
bar.code AS title,
bar.info AS content
FROM bar
UNION ALL
SELECT 'baz.'::text || baz.id AS key,
baz.title AS title,
baz.text AS content
FROM baz) search_data;
All source tables have a GIN index on the column that is mapped to "content" in the view, e.g.
CREATE INDEX bar__info__gin ON bar USING GIN (info gin_trgm_ops);
The combined table has about 200k entries, each source table between 10k and 80k.
When I now execute a query like this
explain (analyze on, timing on)
select "content", 'lorem ipsum dolor sit amet' <-> content as distance
from search_view sv
where "content" ilike '%lorem%ipsum%dolor%sit%amet%'
order by distance desc
limit 10;
then I can see that the query planner does not make use of the indexed content:
QUERY PLAN |
-----------------------------------------------------------------------------------------------------------------------------------------------------------+
Limit (cost=13515.11..13515.13 rows=10 width=36) (actual time=344.365..344.374 rows=10 loops=1) |
-> Sort (cost=13515.11..13515.15 rows=19 width=36) (actual time=344.364..344.369 rows=10 loops=1) |
Sort Key: (('lorem ipsum dolor sit amet'::text <-> search_data.content)) DESC |
Sort Method: quicksort Memory: 25kB |
-> Subquery Scan on search_data (cost=0.00..13514.70 rows=19 width=36) (actual time=225.391..344.355 rows=11 loops=1) |
Filter: (search_data.content ~~* '%lorem%ipsum%dolor%sit%amet%'::text) |
Rows Removed by Filter: 190048 |
-> Append (cost=0.00..11138.92 rows=190059 width=164) (actual time=0.015..146.100 rows=190055 loops=1) |
-> Seq Scan on foo (cost=0.00..1701.05 rows=40003 width=147) (actual time=0.015..18.544 rows=40003 loops=1) |
-> Seq Scan on bar (cost=0.00..4645.03 rows=100002 width=115) (actual time=0.009..39.029 rows=100002 loops=1) |
-> Subquery Scan on "*SELECT* 3" (cost=0.00..2441.38 rows=50050 width=164) (actual time=0.011..34.077 rows=50050 loops=1) |
-> Seq Scan on baz (cost=0.00..1940.88 rows=50050 width=254) (actual time=0.010..18.936 rows=50050 loops=1)|
Planning Time: 0.437 ms |
Execution Time: 344.421 ms e: 344.421 ms |
When I run the query independently against the source tables, the index is leveraged:
explain (analyze on, timing on)
select "info", 'lorem ipsum dolor sit amet' <-> info as distance
from bar b
where "info" ilike '%lorem%ipsum%dolor%sit%amet%'
order by distance desc
limit 10;
QUERY PLAN |
---------------------------------------------------------------------------------------------------------------------------------------------------------+
Limit (cost=95.14..95.16 rows=5 width=81) (actual time=3.064..3.072 rows=10 loops=1) |
-> Sort (cost=95.14..95.16 rows=5 width=81) (actual time=3.062..3.066 rows=10 loops=1) |
Sort Key: (('lorem ipsum dolor sit amet::text <-> (info)::text)) DESC |
Sort Method: quicksort Memory: 25kB |
-> Bitmap Heap Scan on bar b (cost=76.04..95.09 rows=5 width=81) (actual time=2.976..3.052 rows=11 loops=1) |
Recheck Cond: ((info)::text ~~* '%lorem%ipsum%dolor%sit%amet%'::text) |
Rows Removed by Index Recheck: 9 |
Heap Blocks: exact=1 |
-> Bitmap Index Scan on bar__info__gin (cost=0.00..76.04 rows=5 width=0) (actual time=2.945..2.946 rows=20 loops=1)|
Index Cond: ((info)::text ~~* '%lorem%ipsum%dolor%sit%amet%'::text) |
Planning Time: 1.063 ms |
Execution Time: 3.215 ms
What am I doing wrong in the view or how can I get a query against a view make use of the source indexes?
I am using Postgres 13 btw.
Upvotes: 0
Views: 83