Skip to content
Advertisement

Combine 2 GIN indexes with gin_trgm_ops into one | Postgres

I have a flowing table

 create table mytable
(
id       serial     not null primary key,
text_id                      varchar(20)              not null,
customer_unit_id              text,
)

Columns text_id and customer_unit_id basically store codes like K-2021-8524 and similar.

In a web interface I use search window to filter out entries by text_id or customer_unit_id.

Typical search would be like this

SELECT id, text_id
FROM mytable
WHERE UPPER(text_id::text) LIKE UPPER('%2021-8%')
OR UPPER(customer_unit_id ::text) LIKE UPPER('%176%')

I have created to GIN indexes to facilitate search

CREATE INDEX IF NOT EXISTS trgrm_test_text ON mytable
USING gin (Upper(text_id) gin_trgm_ops);

CREATE INDEX IF NOT EXISTS trgrm_test_customer ON mytable
USING gin (Upper(customer_unit_id ) gin_trgm_ops);

I have tried to make 2 column GIN index in order to have one combined index instead of 2 separate – but it doesn’t work (seq scan)

Question – is it possible to have one combined index instead of 2 separate ones fro this exact type of queries???

Thanks….

PostgreSQL version -11

Advertisement

Answer

An alternative would be to create a third column containing a tsvector with the contents of both columns and then index it, e.g.:

ALTER TABLE mytable ADD COLUMN ts tsvector;
UPDATE mytable SET ts =  to_tsvector('english',text_id||' '||customer_unit_id);

CREATE INDEX trgrm_ts_vec_idx2 ON mytable USING gin (ts);

And you’d be able to query it like this:

SELECT id, text_id
FROM mytable
WHERE 
 ts @@ to_tsquery('english', 'k-2021-8 | 176')

In case you cannot afford an extra column, you can use the tsvector only in the index, but it would make queries a little confusing and it should be also a bit slower:

CREATE INDEX IF NOT EXISTS trgrm_ts_vec_idx ON mytable 
USING gin (to_tsvector('english', text_id || ' ' || customer_unit_id));

And query it like this:

SELECT id, text_id
FROM mytable
WHERE 
 to_tsvector('english', text_id || ' ' || customer_unit_id) @@ 
 to_tsquery('english', 'k-2021-8 | 176');

Demo: db<>fiddle

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement