从高截断率到近乎零截断:倒排截断的极致优化

截断率 5% 是什么意思?每 100 个请求里,有 5 个没有完整遍历倒排链就被“砍”掉了。这意味着可能有更好的广告因为截断没有被看到。

把截断率降到 0.19% 后,我理解了一个道理:截断不是因为“没必要遍历”,而是因为“遍历的方式不对”。


为什么需要截断?

倒排链长什么样?假设广告词“北京”有 50 万条广告买了它。每个搜索“北京”相关的请求都要遍历这条链。

遍历 50 万条倒排链 + 每条都要做质量分计算 + 排序 → 耗时不可接受。

传统方案:按质量分预排序倒排链,然后只取前 K 个。K 怎么定?看经验——500?1000?

问题:有些 query 前 200 个就覆盖了所有真正相关的广告,遍历 1000 个是浪费;有些 query 相关性分散,1000 个截断会漏掉很多好广告。


动态截断的设计

核心思想:根据当前已召回结果的质量,动态决定是否继续遍历。

实时跟踪:
- 已召回候选数
- 已遍历倒排链长度
- 最近 N 个候选的平均质量分

当满足以下条件之一时截断:
1. 已召回 ≥ 目标数 AND 连续 50 个候选质量分 < 前 200 个的 30%
2. 已遍历 ≥ 20000 条 AND 近 500 条的质量分无提升
3. 总耗时 > 时间预算的 90%

条件 1 是核心:当倒排链进入“低质区”时及时截断。条件 2 和 3 是安全阀。


分场景差异化

不同广告行业的截断参数不应该一样:

行业 截断参数 原因
医疗行业 保守(遍历多) 相关性高度集中,截断风险大
电商行业 激进(遍历少) 候选多且分散,低质区很快就到
房产行业 中等 地域过滤后候选本身就不多
教育行业 保守 同义表达多,容易漏

在线反馈闭环

截断策略上线后,我们做了一个在线反馈系统:

每隔一段时间,对少量请求(1%)不做截断,完整遍历全链。对比截断结果和全链结果的重叠率,如果重叠率下降超过阈值,自动调大截断参数。

这个闭环让截断率从 高截断率逐步降到近乎零,每个阶段都有数据验证,而不是拍脑袋调参。