PostgreSQL的短语to_tsquery非常慢

时间:2019-06-05 18:27:23

标签: postgresql performance

我正在使用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分钟才能运行?

1 个答案:

答案 0 :(得分:0)

不幸的是,GIN索引不能支持词素的排序。您的第一个查询要快得多,因为它可以使用您建立的索引处理所有内容。对于短语版本,重新检查实际上必须转到您的表并创建ts_vectors才能找到订单。

您也许可以使用RUM索引:https://github.com/postgrespro/rum,其中包括订购信息。

This文章在这些方面做了很大的扩展。