Postgres 多列文本索引

Postgres Multiple Column Text Indexing

如果我 table 有数百万条记录,我正在其中执行通配符搜索,我应该在所有列上建立索引吗?

示例:

table.account_id = X 
AND (table.col1 LIKE '%abc%' 
     OR table.col2 LIKE %abc% 
     OR LOWER(table.col3) LIKE %abc% 
     OR LOWER(table.col4) LIKE %abc%)

这将在大约 1-2 秒内返回,具体取决于我正在搜索的内容。但是,我需要它小于 .5s,因为它是一个自动完成字段。

我的问题是我是否应该创建一个索引,例如:

CREATE INDEX ix_xxxx ON table (col1, col2,lower(col3),lower(col4), owner_firm_id)

还是我应该查看索引中的 to_tsvector 或 text_pattern_ops?

我确实尝试了类似下面的方法,但它没有达到 <1s。

CREATE INDEX ix_name ON table
            USING gist (col1 gist_trgm_ops, col2 gist_trgm_ops, LOWER(col3) gist_trgm_ops, col4 gist_trgm_ops, account_id);

如果执行子字符串搜索,请使用三元组索引:

CREATE EXTENSION pg_trgm;

CREATE INDEX ON atable USING gin ((col1 || ' ' || col2 ... gin_trgm_ops);

然后点赞

WHERE col1 || ' ' || col2 || ... ILIKE '%abcd%'

为了良好的性能,在字符串达到 4 左右的长度之前不要开始搜索。

您的 GiST 索引处理 col4 的方式与查询处理它的方式不同。此外,GiST 索引对列顺序很敏感,可以用最少的工作消除最多行的列应该排在第一位。大概是 account_id:

CREATE INDEX ix_name ON table
   USING gist (account_id, col1 gist_trgm_ops, col2 gist_trgm_ops, LOWER(col3) gist_trgm_ops, lower(col4) gist_trgm_ops);

同一个索引只用GIN而不是GiST形式可能有效,你可以试试看。那一个对列在索引中指定的顺序不敏感。

pg_trgm 索引运算符同样支持 LIKE 和 ILIKE。您可以只使用 ILIKE 而不是 LIKE 对原始列进行查询,然后在原始列上构建索引,而不是对其中两个列执行 lower 。这可能不会对性能产生太大影响,但更简单的索引会更灵活。

但是在您的查询中是否真的有必要使用前导“%”?当人们从中间开始打字时,他们希望自动完成功能起作用吗?