PostgreSQL码农集散地

注意: 这种情况千万不要使用分区表

这种全文检索: 不要使用分区表

https://github.com/timescale/pg_textsearch

pg_testsearch 用来计算 bm25 得分的信息是不是存储在索引中, 由于 PG 没有全局索引, 所以使用分区表时, 跨分区按 bm25 得分排序是无意义的.

是的,您的理解是正确的。pg_textsearch 确实将计算 BM25 得分所需的信息存储在索引中,但对于分区表,每个分区维护自己的统计信息,这使得跨分区按 BM25 得分排序可能没有意义。

核心原因

pg_textsearch 在分区表上使用分区本地统计信息  。每个分区独立维护:

  • 文档总数 (total_docs)
  • 平均文档长度 (avg_doc_len)
  • 用于 IDF 计算的每词文档频率

实际影响

这意味着:

  1. 单分区查询:使用该分区的统计信息计算准确的 BM25 得分
  2. 跨分区查询:每个分区的得分使用不同的统计信息独立计算,可能无法直接比较

测试文件中的示例清楚地展示了这一点  :

-- 小分区(3个文档)中 'database' 的得分  
SELECTcontent, ROUND((content <@> 'database')::numeric, 4) as score  
FROM partition_small;  
-- 结果:-0.4901  

-- 大分区(10个文档)中 'database' 的得分    
SELECTcontent, ROUND((content <@> 'database')::numeric, 4) as score  
FROM partition_large;  
-- 结果:-1.4816  

相同的查询词在不同分区中产生不同的得分,因为 IDF 值依赖于分区本地的文档总数和词频统计。

建议

  • 对于时间分区数据,当得分可比性重要时,建议将时间分区窗口拉到查询需求的最大范围
  • 使用查询自然针对单个分区的分区方案
  • 在设计搜索工作负载的分区策略时考虑此行为

Notes

BM25 得分计算本身在 bm25_text_bm25query_score 函数中实现  ,该函数会从索引中获取必要的统计信息来计算得分。对于分区表,这些统计信息是分区级别的,不是全局的。

最后附一则PG与IvorySQL年度峰会的消息,欢迎报名来济南面基,我是新特性分论坛出品人,欢迎报名参与分享,主委会可解决分享嘉宾住宿和路费。报名地址: https://jsj.top/f/uebqBc