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
。这可能不会对性能产生太大影响,但更简单的索引会更灵活。
但是在您的查询中是否真的有必要使用前导“%”?当人们从中间开始打字时,他们希望自动完成功能起作用吗?
如果我 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
。这可能不会对性能产生太大影响,但更简单的索引会更灵活。
但是在您的查询中是否真的有必要使用前导“%”?当人们从中间开始打字时,他们希望自动完成功能起作用吗?