cheppsn
cheppsn

Reputation: 212

Make use of GIN index in view composed from multiple tables

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

Answers (0)

Related Questions