我需要做一个自动完成功能,需要做这样的事情:
select field from huge_table where field like '%some string%';
该表有 200 万行,我需要它的快速响应和多个响应。我们正在使用 Postgres。这种查询将永远持续下去。
有没有一种有效的方法来使用 postgres 做到这一点?或者也许我应该使用 postgres 以外的其他东西?
谢谢!
我需要做一个自动完成功能,需要做这样的事情:
select field from huge_table where field like '%some string%';
该表有 200 万行,我需要它的快速响应和多个响应。我们正在使用 Postgres。这种查询将永远持续下去。
有没有一种有效的方法来使用 postgres 做到这一点?或者也许我应该使用 postgres 以外的其他东西?
谢谢!
如果您正在执行自动完成,我假设您正在查找基于前缀的匹配项。基于前缀的查找的标准数据结构是trie。
如果使用索引和基于前缀的查找some string%
(
Trie 的最坏情况是O(m)
,其中m
是前缀的长度,因此一旦构建,它将提供非常快速的自动完成功能。
根据您的用例的具体情况,可能值得知道它tsquery
具有用于查询单词前缀的语法。将此与索引tsvector
字段结合起来,您可以非常快速地查找单词前缀。
创建你的“巨大”表:
CREATE TABLE huge_table (
field text,
field_tsv tsvector
);
添加索引:
CREATE INDEX field_tsv_idx ON huge_table USING gin(field_tsv);
添加触发器以更新索引列:
CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON huge_table FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(field_tsv, 'pg_catalog.english', field);
添加一些模拟数据
INSERT INTO huge_table (field) VALUES ('something nice');
INSERT INTO huge_table (field) VALUES ('another thing');
然后查询具有某种限制的前缀:
SELECT field FROM huge_table WHERE field_tsv @@ to_tsquery('anot:*') LIMIT 20;
field
---------------
another thing
(1 row)
您可以为field
正在搜索的内容添加索引。
此外,如果可以避免,请不要使用开放式通配符,因为%some string%
它们确实会损害性能。如果可能的话,做some string%
。
如果您负担得起额外的插入/更新时间,也许您可以使用pg_trgm 扩展
您在该链接中使用 200 万条记录表进行了一些测试,以查看最佳情况下的改进。