内容提要
ParadeDB 通过三项优化显著提升 COUNT 查询速度:按 ctid 分区段跳过可见性检查、反转 DocId 映射减少查找、对高频词用位图替代 BP128 编码。在过滤、排序等复杂查询上,ParadeDB 比 TIN 快 10 至 66 倍,因其将文本与元数据统一索引,可协同过滤和排序。作者强调基准测试取决于工作负载,建议用户自行测试。
延伸解读
COUNT 查询的可见性检查瓶颈
文章指出,在 ParadeDB 中,COUNT 查询超过 80% 的页面访问用于可见性检查,因为每个匹配文档都需要获取并解码其 ctid。TIN 由于直接使用 ctid 作为文档 ID 而可以跳过此步骤。这揭示了在 Postgres 中实现高效 COUNT 的一个关键挑战:如何减少对堆表的随机访问。
段分区如何减少可见性检查
通过按 ctid 对段进行分区,每个段覆盖不重叠的 Postgres 页面范围。这样,如果某个段的所有页面在可见性映射中标记为全可见,就可以跳过整个段的可见性检查。文章提到,在基准查询中,这将可见性相关的页面访问从 1382 次减少到仅 30 次。
反转 DocId 映射以优化 ctid 查找
当段内部分页面需要可见性检查时,ParadeDB 使用反转的 DocId 映射:按页面存储起始 DocId,而不是为每个文档存储 ctid。由于段按 ctid 排序,同一页面的文档具有连续 DocId,因此只需查找需要检查的页面范围。在更新 1000 行后,这将缓冲区访问从 7500 多次减少到不到 400 次。
位图编码对高频词的优势
对于匹配超过 10% 文档的高频词,ParadeDB 使用位图代替 BP128 编码。位图允许按位与/或操作一次处理 64 个文档,而 BP128 需要逐个遍历数组。文章指出,这一改变将 Wikipedia COUNT 基准的 p99 延迟减半。
Q&A
ParadeDB 是如何让 COUNT 查询变快的?
ParadeDB 通过三项优化提升 COUNT 查询速度:1) 按 ctid 分区段,使每个段拥有不重叠的 Postgres 页范围,从而可以跳过可见性检查;2) 反转 DocId 映射,用压缩列记录每个页的起始 DocId,减少查找次数;3) 对高频词使用位图替代 BP128 编码,降低交集和并集开销。
ParadeDB 在过滤和排序查询上比 TIN 快多少?
在过滤、排序等复杂查询上,ParadeDB 比 TIN 快 10 至 66 倍。例如,带分数过滤的 COUNT 查询快 10 倍,带分数过滤的 Top K 查询快 11.6 倍,按时间排序的 Top K 查询快 21.7 倍。
为什么 ParadeDB 在复杂查询上比 TIN 快?
因为 ParadeDB 将文本和元数据统一索引,可以协同过滤和排序,而 TIN 是纯文本索引,非文本过滤和排序依赖 B-tree 索引,需要独立产生匹配后再合并,导致大量无用功。
ParadeDB 的段分区(segment partitioning)是如何工作的?
段分区基于 Spooky LSM 压缩论文,允许按一个或多个列的值拆分段。例如按 ctid 分区后,每个段拥有不重叠的 Postgres 页范围,这样可以将 ctid 范围与可见性映射对比,如果整个范围都是 all-visible,就可以跳过该段的可见性检查。
ParadeDB 如何优化 DocId 到 ctid 的映射?
ParadeDB 反转了 DocId 映射:不再为每个文档存储 ctid,而是用压缩列记录每个 Postgres 页的起始 DocId。由于段已按 ctid 排序,同一页上的文档具有连续的 DocId,因此只需对需要检查的页查找文档范围,大幅减少查找次数。
ParadeDB 在什么情况下使用位图表示 posting list?
对于匹配文档数超过 10% 的高频词,ParadeDB 使用位图表示 posting list,因为位图可以一次处理 64 个文档,比 BP128 数组逐项遍历更高效。
ParadeDB 的基准测试结果是否意味着它是最快的搜索引擎?
不是。作者强调基准测试取决于工作负载,没有单一基准能证明谁最快,尤其是由产品团队自己设计的基准。建议用户在自己的数据和查询上测试。