我正在使用PostgreSql 9.6
我有一个约有1600万条记录的数据库表。我有一个jsonb列-logentry-它具有一个称为“消息”的字段。它具有如下创建的GIN索引:
CREATE INDEX inettklog_ix_ts_message
ON public.inettklog USING gin
(to_tsvector('english'::regconfig, logentry ->> 'message'::text))
TABLESPACE pg_default;
我要搜索“应用程序名称”。
带有WHERE子句的查询
to_tsvector('english', logentry->>'message') @@ plainto_tsquery('application name')
以113毫秒的速度执行并返回7349行
解释分析:
WindowAgg (cost=1812.98..2240.22 rows=95 width=12) (actual time=84.037..84.986 rows=7315 loops=1)
-> Bitmap Heap Scan on inettklog (cost=1812.98..2239.03 rows=95 width=4) (actual time=17.943..81.708 rows=7315 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, (logentry ->> 'message'::text)) @@ plainto_tsquery('application name'::text))
Heap Blocks: exact=7574
-> Bitmap Index Scan on inettklog_ix_ts_message (cost=0.00..1812.96 rows=95 width=0) (actual time=8.542..8.542 rows=8009 loops=1)
Index Cond: (to_tsvector('english'::regconfig, (logentry ->> 'message'::text)) @@ plainto_tsquery('application name'::text))
Planning time: 0.387 ms
Execution time: 85.243 ms
但是我不想要“应用程序”和“名称”,我想要“应用程序名称”
但是查询的WHERE子句为
to_tsvector('english', logentry->>'message') @@ phraseto_tsquery('application name')
需要2分钟才能运行!
解释分析:
WindowAgg (cost=852.98..1280.22 rows=95 width=12) (actual time=145065.204..145066.127 rows=7314 loops=1)
-> Bitmap Heap Scan on inettklog (cost=852.98..1279.03 rows=95 width=4) (actual time=55.180..145030.148 rows=7314 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, (logentry ->> 'message'::text)) @@ phraseto_tsquery('application name'::text))
Heap Blocks: exact=7573
-> Bitmap Index Scan on inettklog_ix_ts_message (cost=0.00..852.96 rows=95 width=0) (actual time=8.196..8.196 rows=8008 loops=1)
Index Cond: (to_tsvector('english'::regconfig, (logentry ->> 'message'::text)) @@ phraseto_tsquery('application name'::text))
Planning time: 25.926 ms
Execution time: 145067.052 ms
“ <->”运算符的工作原理是首先找到包含“应用程序”和“名称”的行,然后过滤结果以查找“名称”紧随“应用程序”的行。
如果是的话,为什么要花2分钟才能运行?
答案 0 :(得分:0)
不幸的是,GIN索引不能支持词素的排序。您的第一个查询要快得多,因为它可以使用您建立的索引处理所有内容。对于短语版本,重新检查实际上必须转到您的表并创建ts_vectors才能找到订单。
您也许可以使用RUM索引:https://github.com/postgrespro/rum,其中包括订购信息。
This文章在这些方面做了很大的扩展。