2009-10-08 133 views
15

我使用来自StackOverflow的9月数据转储作为示例数据来测试PostgreSQL文本搜索功能。 :-)为什么PostgreSQL文本搜索GiST索引比GIN索引慢得多?

使用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'; 

但是,当我创建梗概指数,结果却大相径庭。整个过程不到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本身提供的功能。

回答

5

尝试

CREATE INDEX PostText_GIST ON Posts USING GIST(PostText varchar_pattern_ops); 

它创建适合前缀查询索引。请参阅Operator Classes and Operator Families上的PostgreSQL文档。 @@运算符只对term矢量有意义; GiST索引(使用varchar_pattern_ops)将会给LIKE带来极好的结果。

+0

谢谢您的回答部分,我我会尝试你的建议... – 2009-10-09 20:35:03

+1

它必须花费相当多的时间才能生成该索引。 :) – 2009-12-11 03:56:40

+5

这不可能工作,因为'varchar_pattern_ops'用于'varchar'类型,'PostText'是'tsvector'类型,它只被定义为'btree'和'hash'索引而不是'gist'。 – 2011-01-04 20:22:13

2

顺便说一句:如果没有得到回答让您满意的是,在这里你做

SELECT * FROM Posts WHERE PostText @@ 'postgresql';

应该已经

SELECT * FROM Posts WHERE PostText @@ to_tsquery('postgresql');

+0

感谢您的提示,下次我测试PostgreSQL时我会尝试一下。我几年来一直在使用MySQL。 – 2013-07-18 18:25:43