PostgreSQL 9.6 全文搜索的短语频率计数器

Phrase frequency counter with FULL Text Search of PostgreSQL 9.6

我需要针对索引文本字段(ts_vector 数据类型)使用 ts_query 计算短语出现的次数。它可以工作,但速度很慢,因为 table 很大。对于单个单词,我预先计算了所有频率,但我不知道如何提高短语搜索的速度。

编辑:感谢@jjanes 的回复。

这是我的查询:

SELECT substring(date_input::text,0,5) as myear, ts_headline('simple',text_input,q, 'StartSel=<b>, StopSel=</b>,MaxWords=2, MinWords=1, ShortWord=1, HighlightAll=FALSE, MaxFragments=9999, FragmentDelimiter=" ... "') as headline 
FROM 
db_test, to_tsquery('simple','united<->kingdom') as q WHERE date_input BETWEEN '2000-01-01'::DATE AND '2019-12-31'::DATE and idxfti_simple @@ q 

这是 EXPLAIN (ANALYZE, BUFFERS) 输出:

Nested Loop  (cost=25408.33..47901.67 rows=5509 width=64) (actual time=286.536..17133.343 rows=38127 loops=1)
Buffers: shared hit=224723
    ->  Function Scan on q  (cost=0.00..0.01 rows=1 width=32) (actual time=0.005..0.007 rows=1 loops=1)
    ->  Append  (cost=25408.33..46428.00 rows=5510 width=625) (actual time=285.372..864.868 rows=38127 loops=1)
        Buffers: shared hit=165713
        ->  Bitmap Heap Scan on db_test  (cost=25408.33..46309.01 rows=5509 width=625) (actual time=285.368..791.111 rows=38127 loops=1)
            Recheck Cond: ((idxfti_simple @@ q.q) AND (date_input >= '2000-01-01'::date) AND (date_input <= '2019-12-31'::date))
            Rows Removed by Index Recheck: 136
            Heap Blocks: exact=29643
            Buffers: shared hit=165607
                ->  BitmapAnd  (cost=25408.33..25408.33 rows=5509 width=0) (actual time=278.370..278.371 rows=0 loops=1)
                Buffers: shared hit=3838
                    ->  Bitmap Index Scan on idxftisimple_idx  (cost=0.00..1989.01 rows=35869 width=0) (actual time=67.280..67.281 rows=176654 loops=1)
                        Index Cond: (idxfti_simple @@ q.q)
                        Buffers: shared hit=611
                    ->  Bitmap Index Scan on db_test_date_input_idx  (cost=0.00..23142.24 rows=1101781 width=0) (actual time=174.711..174.712 rows=1149456 loops=1)
                        Index Cond: ((date_input >= '2000-01-01'::date) AND (date_input <= '2019-12-31'::date))
                        Buffers: shared hit=3227
        ->  Seq Scan on test  (cost=0.00..118.98 rows=1 width=451) (actual time=0.280..0.280 rows=0 loops=1)
            Filter: ((date_input >= '2000-01-01'::date) AND (date_input <= '2019-12-31'::date) AND (idxfti_simple @@ q.q))
            Rows Removed by Filter: 742
            Buffers: shared hit=106

Planning time: 0.332 ms
Execution time: 17176.805 ms

抱歉,我无法将 track_io_timing 设置为开启。我知道 ts_headline 不被推荐,但我需要它来计算一个短语在同一字段中出现的次数。

提前感谢您的帮助。

版本 9.2 已旧且不受支持。它首先没有对短语搜索的本地支持(在 9.6 中引入)。

请升级。

如果它仍然很慢,请向我们展示查询和它的 EXPLAIN (ANALYZE, BUFFERS),最好打开 track_io_timing。

请注意,Bitmap Heap Scan 中获取行的速度非常快,<0.8 秒,而且几乎所有时间都花在了顶级节点上。那段时间很可能花在 ts_headline 上,重新解析 text_input 文档。只要您继续使用 ts_headline,您就无能为力了。

ts_headline 不会直接给你你想要的(频率),所以你必须对它进行某种 post 处理。也许您可以直接 post 处理 tsvector,这样文档就不需要重新解析了。

另一种选择是进一步升级,这可以让 ts_headline 的工作分散到多个 CPU 上。 PostgreSQL 9.6 是第一个支持并行查询的版本,那个版本还不够成熟,无法并行化这种东西。 v10 可能足以对此进行并行查询,但您不妨一直跳到 v12。