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。
我需要针对索引文本字段(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。