我正在测试PostgreSQL文本搜索功能,使用StackOverflow的9月数据转储作为样本数据。 : - )
使用LIKE
谓词或POSIX正则表达式匹配搜索120万行的天真方法需要 90-105秒(在我的Macbook上)进行全表扫描搜索关键字。
SELECT * FROM Posts WHERE body LIKE '%postgresql%';
SELECT * FROM Posts WHERE body ~ 'postgresql';
未经编制索引的临时文字搜索查询大约需要 8分钟:
SELECT * FROM Posts WHERE to_tsvector(body) @@ to_tsquery('postgresql');
创建GIN索引需要 40分钟:
ALTER TABLE Posts ADD COLUMN PostText TSVECTOR;
UPDATE Posts SET PostText = to_tsvector(body);
CREATE INDEX PostText_GIN ON Posts USING GIN(PostText);
(我意识到我也可以通过将其定义为表达式索引来一步完成。)
之后,由GIN索引辅助的查询运行得更快 - 这需要 40毫秒:
SELECT * FROM Posts WHERE PostText @@ 'postgresql';
但是,当我创建GiST索引时,结果会有很大差异。创建索引需要不到 2分钟:
CREATE INDEX PostText_GIN ON Posts USING GIST(PostText);
之后,使用@@
文本搜索运算符的查询需要 90-100秒。因此,GiST索引确实将未编制索引的TS查询从8分钟改进为1.5分钟。但与使用LIKE
进行全表扫描相比,这没什么改进。它在Web编程环境中毫无用处。
我是否遗漏了使用GiST索引至关重要的内容?索引是否需要预先缓存在内存中?我正在使用MacPorts的普通PostgreSQL安装,没有调整。
使用GiST索引的推荐方法是什么?或者每个用PostgreSQL做TS的人都跳过GiST索引并只使用GIN索引吗?
PS:我确实知道像Sphinx Search和Lucene这样的替代品。我只是想了解PostgreSQL本身提供的功能。
答案 0 :(得分:6)
试
CREATE INDEX PostText_GIST ON Posts USING GIST(PostText varchar_pattern_ops);
创建适合前缀查询的索引。请参阅Operator Classes and Operator Families上的PostgreSQL文档。 @@运算符仅对术语向量有意义;使用LIKE,GiST索引(使用varchar_pattern_ops)将获得出色的结果。
答案 1 :(得分:6)
如果您感兴趣,文档可以很好地概述GiST和GIN索引之间的性能差异:GiST and GIN Index Types。
答案 2 :(得分:2)
SELECT * FROM Posts WHERE PostText @@ 'postgresql';
应该是
SELECT * FROM Posts WHERE PostText @@ to_tsquery('postgresql');