Ming Ying:让 COUNT 查询与其余搜索操作真正快起来(第二部分)

Ming Ying:让 COUNT 查询与其余搜索操作真正快起来(第二部分)

💡 原文英文,约2600词,阅读约需10分钟。
📝

内容提要

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 的基准测试结果是否意味着它是最快的搜索引擎?

不是。作者强调基准测试取决于工作负载,没有单一基准能证明谁最快,尤其是由产品团队自己设计的基准。建议用户在自己的数据和查询上测试。

🏷️

标签

➡️

继续阅读