构造反证问题的核心,是把“这个假设如果成立,应该还能看到什么”变成可以观察、可以否定的预测。缺少完整数据或权限时,不必等全量日志到手,先找一条最便宜的区分性证据:要么排除竞争解释,要么让假设做出方向明确的预测。反证问题的价值不在于证明假设正确,而在于找出它与别的解释分道扬镳的地方。
一个性能现象往往同时兼容多个原因。比如“某类页面加载变慢”,可能来自服务端响应变长、第三方资源阻塞、缓存命中下降,也可能只是统计口径变化。此时不要急着收集更多同类指标,而是先把解释写全,再为每个解释写一句“如果它为真,那么X应当出现;如果X不出现,它就站不住”。
反证问题的形式通常是:假设H成立,那么在条件C下,观察O应当出现;若O不出现,则H至少不是主因。关键在条件C要能区分H与其他解释。例如服务端变慢与前端资源变慢都会拉高整体加载时间,但前者应同时影响不加载该资源的页面,后者只影响引用该资源的页面。这个“是否同时影响无关页面”就是一条区分性条件。
缺少权限时,可用的观察包括:同一模板不同页面的相对差异、同一资源在不同入口下的表现、公开的第三方估算与站内统计的口径差异。第三方估算流量、搜索引擎报告与站内统计口径不同,不能直接相减当作因果,但口径差异本身可以成为反证线索:如果两个来源对同一时段的趋势方向相反,说明至少有一个假设依赖了不可比的数据。
此时优先构造“分层反证”。把问题按可区分的维度切开,例如按页面模板、资源来源、用户是否命中缓存、请求是否经过某段链路。做法是:先提出假设,再指定一个应当出现差异的切分维度,然后只查这个维度上的对比。
实际动作举例:假设“慢来自第三方脚本”,就查同一模板中引用与不引用该脚本的页面,比较其加载耗时的分布。若两组分布几乎重合,该假设被削弱;若差异明显且方向一致,再进入下一步,查该脚本的加载失败率或阻塞时长。这个动作的结果直接决定下一步是继续追第三方,还是回头查服务端或缓存。
此时无法做精细分层,反证问题要改为“时间与人群的错位检验”。可用的动作是:找一个假设不应当影响的时间段或人群,看该处是否同步变化。若假设只影响移动端,桌面端不应同幅变化;若假设只影响某入口,其他入口不应同步。
但要注意,聚合数据里的同步变化有多种解释:可能是共同的上游依赖、统计口径调整、采集覆盖变化,也可能只是季节性波动。因此聚合层面的反证只能削弱假设,不能单独确认原因。可执行的最小动作是:固定一个对照维度,记录假设组与对照组的相对方向,并注明哪些解释仍未被排除。若两组同向变化,优先怀疑共同上游或口径变化;若只有假设组变化,才值得投入更多权限去取原始数据。
常见错误是把反证写成“再确认一下这个指标是否也变差”。这类描述几乎总能找到支持证据,因为它没有规定失败条件。有效的反证问题必须包含否定结果:
强形式的好处是,无论结果如何都能推进判断。结果符合预测,假设获得支持但仍需排除共同原因;结果不符合,假设被削弱,直接转向竞争解释。构造时可用若……则……否则……的句式自查,确保“否则”分支真的能发生。
反证问题也有失效场景。第一,当多个解释预测同一观察时,该观察不具备区分力,需要换维度。第二,当数据采集本身受问题影响时,比如慢请求更容易被采样丢失,观察到的分布可能失真,此时应先检查采集完整性。第三,请求量、抓取量或某项统计归零,不能单独证明处理正确,它也可能是采集中断、权限变更或口径调整的结果,需要结合对照维度判断。
还要区分相关与因果:即使假设组与对照组出现预期差异,也只能说明该假设与现象一致,不能仅凭一次对比还原完整机制。反证的作用是缩小候选解释集合,而不是给出唯一答案。缺少完整数据时,可执行的最小动作是先固定一条区分性条件并记录否定结果;若该条件无法区分,就换条件,而不是堆更多同类指标。这样每一步都能为下一步提供取舍依据,也避免在证据不足时过早下结论。