
37%准则这个词我第一次真正体会到分量是在处理一个棘手的慢SQL优化任务时。当时面对一张千万级订单表索引加了好几个SQL改写三版性能还是卡在2秒以上。组里一位老前辈路过看了眼说你调研的样本量够了别等了动手改吧。后来我才知道他说的够了背后藏着一个数学模型——最优停止理论里的37%准则。这个准则讲的是如果你要在N个候选里选一个最好的又必须按照顺序逐个考察、且无法回头重选那么最优策略是——先观察前37%的候选只看不选只记住其中最好的是什么水平从第37%之后开始一旦遇到任何一个超过这个参考基准的候选立刻就地选定不再犹豫。这样操作你选到全局最优的概率最大而这个最大概率也恰好是37%。这篇文章我想把它掰开揉碎讲清楚它为什么成立以及真正把它用进SQL优化、性能调优、产品选型和团队决策时它到底能帮我们省下多少时间。1. 为什么优化工作里最该先学的是怎么停止优化先聊一个听起来反直觉的问题大部分优化工作越做越久真不是能力问题而是没有决策截止点。我自己早期做优化也有这个毛病。拿到一个性能问题先看执行计划再翻慢查询日志接着去查索引统计信息然后改配置参数改完测一轮不理想又回到第一步……循环往复。最夸张的一次我优化一个接口花了整整三天最后收益和第一天加索引的收益几乎一样。那一刻我意识到在优化这个动作里真正让人消耗殆尽的不是技术难度而是什么时候停止探索、开始行动这件事没有标准答案。37%准则就是给这个停止点一个数学答案。1.1 秘书问题一个被低估的决策模型37%准则来自一个经典数学模型叫秘书问题Secretary Problem也叫最优停止问题。它描述的场景是这样的假设你是招聘经理有N个候选人按随机顺序依次来面试你要当场决定录不录用。规则有两条——第一每个候选人面试完必须立即做决定不可以等看完后面的人再回头选前面的第二你的目标不是找个差不多能干的而是必须选到所有人里最优的那个。太早下定决心大概率错过后面更好的人等得太晚真正的人才又被前面的人挤掉了。N越大凭感觉决策越不靠谱。数学家给出的结论很干净最优策略是先拒绝前N/e个候选人e是自然对数底数约2.718数量上就是前37%左右。这37%的人纯粹用来建立什么水平算好的判断基准谁都不选。之后从第37%加一个开始一旦遇到比基准里最好的那人更好的立刻录用。这个策略能把选到最优候选人的概率提升到约37%相比之下随缘选或者看一半再选的成功率都低得多。我第一眼看到这个结论时觉得很神奇一个如此简单的规则居然是从几百个N值下通用推出来的数学结果。更让我惊讶的是它不只在招聘里有用凡是要从一堆顺序出现的选项里挑一个、而且没法回头的场景几乎都能套用。1.2 37%为什么是37%直觉与推导先给不习惯数学的读者一个直观版本。你决策时面临一个“探索—利用”的拉扯探索太少你根本不知道好选项长什么样后面遇到好机会也认不出来探索太多你又被规则限制过了这村没这店眼睁睁看着好机会从手边溜走。37%恰好是探索和利用之间的平衡点。往深一点说这个结论背后用到的是概率的连续化近似。假设N个候选者的水平做一个排序最好的排第1名。你选择的时刻发生在第k个候选人之后那么你成功的概率大致可以写成$$P(\text{成功}) \approx \frac{k}{N}\int_{k/N}^{1}\frac{1}{x},dx$$这里积分算完是 $-\frac{k}{N}\ln\frac{k}{N}$。你只要对这个函数求最大值就能发现它取最大值时的 $k/N$ 正好等于 $1/e$也就是约0.3679。所以前37%观察、后63%行动是最优的。为了让自己心服口服我写过一个小脚本做过蒙特卡洛模拟在不同阈值比例下分别跑了10万次结果和理论高度吻合import random import math def simulate(n, stop_ratio): k max(1, int(n * stop_ratio)) best_so_far -float(inf) # 观察阶段只看不选 for i in range(k): best_so_far max(best_so_far, random.random()) # 行动阶段超过基准就选 for i in range(k, n): val random.random() if val best_so_far: return val max_val return False def run_experiments(n, stop_ratio, trials100000): max_val None # 这里略去预生成最大值仅示意结构 win 0 for _ in range(trials): arr [random.random() for _ in range(n)] max_val max(arr) k max(1, int(n * stop_ratio)) best_so_far max(arr[:k]) picked False for val in arr[k:]: if val best_so_far: picked val max_val break if picked: win 1 return win / trials for ratio in [0.2, 0.367, 0.5, 0.8]: print(ratio, run_experiments(100, ratio))跑出来的结果很有意思0.37附近成功率最高而且30%到40%这个区间差距不大都在35%上下。这给我一个额外启发——你不需要把37%卡得那么精确落在一个合理区间就行。真正致命的错误是只观察10%就急着行动或者观察到60%还不做决定。2. 把37%准则翻译成工程师能用的语言聊完数学我想回到大家更熟悉的领域技术优化。不管是SQL优化、服务端性能调优还是移动端卡顿治理本质上都是从一堆可选操作里按顺序尝试找到最有效的那一个。但是多数人做的事和37%准则背道而驰。最常见的错误是什么是把所有能想到的优化手段全做一遍再说。明天先加索引后天改分页大后天调缓存最后发现前面两步白干了回滚还费半天劲儿。我见过有人为了优化一个接口一遍遍开着慢查询日志、profile、performance_schema收集了满满十几页数据但问题核心早就在前几页里暴露了。收集数据这件事做着做着就容易变成拖延的理由。2.1 优化流程里的观察期和行动期用37%准则重新设计一次性能优化的流程可以拆成两个阶段。先说观察期。假设你面对一个未知系统列出的潜在优化点有N个比如索引设计、SQL改写、连接池参数、缓存引入、数据归档、硬件配置……你不可能在动手前把每个点的收益都精确预判出来。合理的做法是先快速尝试前37%的措施——不是做完并长期观测而是做个最小验证量化出效果趋势。这段观察期要忍住优化冲动即使某个手段看起来收益不错也不要立刻深挖。因为你的任务是建立基准而不是锁定方案。举例说慢SQL排查里你通过explain和慢日志锁定5类候选问题缺索引、join过多、select了不需要的列、order by导致filesort、隐式类型转换。5的37%约等于2次也就是前两个问题你只管看方案、估算回表和扫描行数不动手。走完这两步你心里对这表什么量级、什么访问模式、瓶颈在哪已经有了清晰轮廓。从第3个措施开始一旦它明显优于前面观察到的基线立刻全力投入。我在实际操作中的体会是这套流程的价值不在于精确的百分比而在于它强制你先把观察和行动分离开。没有这个分离人的本能是哪个方法听着省事就先试哪个最后优化变成堆砌。2.2 实战案例慢SQL优化中的37%决策拿一个我处理过的真实case来对照。某订单查询接口响应1200ms查询频率极高。我用慢日志抓出主查询后列出可动手的方向A加复合索引、B改子查询为join、C减少返回字段、D把排序字段加入索引避免filesort、E调整MySQL的buffer pool、F拆分历史数据表。按37%规则N6观察期做的是前2项约2.2取整也就是A和B。我先不深改代码只做explain分析加索引推演。看执行计划发现lines字段是text类型且必查回表严重join的驱动表选反了。这时我已经知道大方向不是内存参数而是减少回表和调整驱动表。进入行动期后第三个方向C减少返回字段一试——行数从扫描6万行直接降到1.8万耗时降到280ms。按规矩我应该停止继续尝试D和E了。但那天我没忍住顺手把D也做了最后降到了180ms。收益确实有但回头算笔账C方案的性价比大约是一行SQL改动换900ms收益D方案是重建一个索引、验证半小时换100ms收益。如果在后来的运维里D成了负担索引写放大那更是得不偿失。这个case给我的教训是37%准则说到底是教你管理决策成本的不是让你追求单次收益最大化。当收益曲线已经进入平台期再投入的边际回报就极为有限。2.3 为什么不能把问题全查清楚再动手有人会杠做优化不得先把所有情况摸清楚吗不全查清楚万一漏掉了那个最优解怎么办这个担忧看似合理但在真实世界里它有一个被忽略的成本——时间。每多排查一个点你就多花一段时间。真正的问题在于排查本身也有机会成本而且大部分系统的性能问题服从长尾分布前两三个关键手段通常能解决80%的问题。这意味着你把第4个、第5个潜在原因查清楚能获得的边际信息非常少。37%准则还有一个隐藏前提候选出现的顺序是随机的你不能预测下一个候选是否一定更好。这和性能优化的实际情况高度吻合——你列出的优化方案清单获益水平基本是随机的你无法事前预判哪个收益最大。既然无法预判最优策略就是少预测、多对比、设门槛。把时间花在设计更好的门槛上比花在无限排查上划算得多。我自己的经验是优化任务开始前先定一个行动触发线效果达到多少就算达标。如果做了前37%的观察还是没头绪也别急着全查停下来重新定义问题往往比继续钻牛角尖好。3. 产品与运营优化用门槛规则终结选择困难把37%准则从技术性能挪到产品优化和运营决策里它依然能用因为这些场景有一个共性方案池是顺序出现的你必须在有限时间内选一个重点投入而且选了之后反悔成本很高。做功能迭代尤其如此。我记得有次参与一个支付转化率优化项目产品组一口气整理了9个优化点首屏优惠信息前置、按钮颜色、登录方式简化、支付方式排序、文案修改、优惠倒计时、渲染性能优化、客服入口后移、提交按钮防抖。按9的37%计算大约3.3个也就是前3个方案用来观察后面遇到超越前3个平均表现的方案就定下来。现实操作里产品经理往往不是这么干的。他们会做一个全量实验矩阵9个点全测试一轮每个跑两周最后看数据再决定。时间成本是2-3个月竞品早就迭代了两轮。更常见的是老板拍板先做他觉得最靠谱的按钮颜色做完了没效果再试下一个凭感觉排序导致节奏完全混乱。3.1 再优化一版背后的模型缺失产品优化里最消耗团队士气的三个字是再想想。功能上线数据不理想第一反应不是看数据也不是继续做下一个候选而是把当前功能推翻重来。而据我观察推翻重来的大概率又是一个没有对标基准的拍脑袋版本效果和之前半斤八两。用37%准则做一套简单的决策框架可以这样操作把优化候选按启动顺序排列前37%作为对照观察组不许投入深开发只做轻量上线或灰度测算出基础转化率作为阈值。从第37%之后的候选方案里凡是预估收益能超过那个阈值、且实现成本不高的就可以立即定为重点方案投入深攻。这里面的关键点是产品优化里我们真正缺的很多时候不是想法而是一个什么时候可以停止生成新想法开始在已生成的想法里做选择的标准。37%门槛就充当了这个标准。3.2 用门槛规则取代再想想A/B测试与候选方案筛选A/B测试和37%准则可以结合得很好。很多人做A/B测试的问题是实验数量无限膨胀每个小变化都开一个实验最后每组的样本量都不够结论全是噪声。引入37%思维以后流程变成这样假设有N个实验想法先不做N个实验而是把前37%想法合并成探测包用最低成本快速抢跑一遍得到一组基准数据。然后从剩余63%里挑选那些在方向上与探测包最优结果明显不同的高优先级想法做单点实验。这样做实验总量变少但每个实验的样本充足、结论可信。我在某个内容产品的推荐页优化里就是这么干的。7个候选优化点我强制要求团队在前3个只做埋点和轻量开关验证不做复杂开发。结果发现推荐解释理由外露这个方向带来的点击提升远超其他方向于是把后续精力和开发资源全压到这条线上。最后复盘发现如果我们按传统思路平均用力效果最好的那个方向反而会被平庸的方案分流掉一部分时间。3.3 从37%到帕累托两种二八如何合作帕累托法则说80%的结果来自20%的投入37%准则说的是用37%的样本建立基准。两者并不矛盾而是配合使用。37%准则是决策前的策略它帮我们确定在哪里停止寻找更多选项帕累托法则是决策后的资源分配策略它告诉我们在既定方案内部把80%的资源倾注在那20%的关键杠杆点上。拿优化案例说先用37%准则选出应该投入的那个方案然后用帕累托法则找到方案内部的关键模块重点打磨。我在数据库优化的一个项目里正是用37%准则锁定了I/O瓶颈这个方向然后顺着这个方向做了I/O合并、预读、冷热分离三步优化每一步明显迭代。如果顺序反过来先盲目应用二八定律随便挑一个模块优化我大概率会浪费两三天。4. 技术选型与团队决策中的37%应用除了具体的代码优化和产品迭代37%准则在更高维度的决策里同样有很好的指导意义比如技术选型、团队招聘、项目排期。这些场景的共同特征是选项像流水一样来到你面前而你的决策窗口是有限的。4.1 技术调研期限调研本身也要设停做技术选型是最容易陷入调研无底洞的事。尤其这几年中间件、框架、数据库新东西层出不穷每个方案都有对应的博客、源码解读、踩坑帖越看越觉得自己还没研究透不敢拍板。我在做一次数据库选型时给自己定了一个硬性规则候选方案有5个调研时间只有前2个方案的周期5的37%约1.85取2。也就是说前2个方案我只看架构和核心场景测试不做深度压测从第3个方案开始如果它在前2个方案建立的评估标准上超越任何一个就马上组织深测。最终选定的那个方案并不是全项第一但在核心读写场景上是明显领先的而且它的优先定下来让团队提前两周进入开发。另一种常见做法是等到调研100%完成再开工表面稳健实际上损失的是市场窗口和团队热情。所谓的完美选型根本不存在你需要的是够好的选型。37%准则给的就是这个够好的停止线。4.2 面试、换方向与跳槽决策的启发37%准则在招聘里的含义很容易误解不是说必须淘汰前37%的候选人而是说面试官前期的37%面试主要用于校准自己的评价尺度。举个例子如果你想招一名资深后端前面来的5个人你心里都没底没关系这5个人就是你的参照系帮你理解当前市场行情到底什么水平、简历上的精通和实际能力之间差距多大。从第6个人开始一旦遇到你觉得明显优于前5个平均水平的候选人就要果断推进offer。跳槽场景也一样。你手握N个机会不可能等所有机会都面完再选每个offer又有有效期。比较好的策略是前面收到的offer别急着签用它们建立市场价基准线当后续机会出现时只要在总包、方向、成长性三项里有明显突破基准线的就可以重点接触和决策。我见过太多人选offer时因为后面可能还有更好的而把前面的好机会全部放走最后落得两手空空。这个模型的本质是帮你抵抗FOMO错失恐惧。你不可能在所有信息都齐备后才做决定你唯一能控制的是在什么时候停止收集信息。4.3 迭代排期里的停止信号Unity/移动端优化的启发移动端和游戏性能优化是另一个典型场景。通常一个Unity项目要优化的话候选动作非常多合批、减面、贴图压缩、代码GC优化、资源异步加载、Shader简化、遮挡剔除、LOD、包体裁剪、预加载策略……每一件扔进排期里都能吃下一两周。这时候团队最需要的就是停止信号而37%准则恰好能提供一个客观的停止线。比如有10个优化方向前4个37%用来快速采样找到当前最突出的性能瓶颈类型一旦确定瓶颈方向后面的优化动作只要持续贡献收益就继续沿着这个方向深挖直到连续几个动作的收益都跌到初始峰值的1/4以下就判断优化收益平台期到了可以停下来做性能回归和发版准备。我在一个Unity小游戏的帧率优化中切身体会到最深的一次性能提升发生在第3个动作合批调整上但如果当时没有用观察期先跑前2个动作我很容易直接陷在改代码GC这种听着高级、实际收效甚微的深坑里。这让我更确信优化排期前先定停止条件比排期表本身更重要。5. 实操指南把37%准则落地到自己的项目聊了这么多场景我来汇总一套可以直接落地的操作流程。这套流程我反复用过从性能优化到功能选型都吃得住核心是五步。5.1 一个五步落地流程第一步列出候选清单。凡是你觉得可能有效的优化动作先写下来编号不评价。注意这里不需要做可行性排序因为排序会引入主观判断反而破坏随机性。第二步设定观察期的长度。计算N × 0.37四舍五入得到一个整数k这就是你只看不做的候选个数。N小于等于3的时候这个规则就不太适用了我后面会专门说边界条件。第三步执行观察期。对前k个候选方案做最小成本的验证或数据收集不深究、不优化、不投入重资源。目标很单纯建立一个可靠的基准线。这个基准线可以是性能指标、转化数据、成本数据或用户反馈只要能量化就行。第四步在行动期执行门槛规则。从第k1个候选开始每评估一个就把它和基准线比较——如果它显著优于基准线果断选择它并终止评估如果不优于继续看下一个。这个过程最忌讳的是再等等看下一个这违背了整个模型。第五步做止损保护。选定方案后给自己设定一个验证周期和关闭条件如果一段时间后收益不达预期或者后续出现了新的明显更优的证据就立即重复一轮观察—更新基准—再决策。37%准则不是一锤子买卖它是可以滚动使用的。五步看着简单真正执行起来容易在第三步和第四步翻车。第三部的坑是忍不住手痒总想顺手把第k个方案的优化也做了第四步的坑是这个方案已经很好了但下一个万一更好怎么办。这两条我都踩过这里一并提醒。5.2 边界条件什么时候别用37%37%准则有它的适用范围不是万灵丹。我必须把边界条件讲清楚免得有人拿它硬套。第一当你能以低成本反复比较全部选项时不要用。比如A/B测试能在几个方案之间快速跑流量直接做全量对比就好用37%反而人为压缩了信息量。第二当失败代价极大、不可承受时不要用。例如医疗诊断、系统核心架构的不可逆迁移这类决策应该以完备信息为准而不是追求概率最大。37%准则本质是风险管理工具不是安全保证。第三当候选数量太少时N小于5不要机械套用。用观察期留下的候选样本太少了门槛规则基本失效。这时候凭经验和系统分析直接做判断远比套公式靠谱。第四当顺序本身有强信息时不要用。比如候选方案有明确的从劣到优排列趋势或者方案按优先级排序好了那37%的随机性假设就不成立了。它的数学推导前提是候选顺序随机。边界条件不是打击使用信心而是防止滥用。我在自己团队里常常强调一句话没有工具是放之四海而皆准的但理解工具的适用范围本身就是一种专业度。5.3 需要N吗不知道N怎么办有朋友会问我在很多真实场景里根本不知道总候选数量N是多少比如优化一个系统的潜在手段无穷无尽还要怎么算37%我的经验是分两种情况。一种情况是你可以自己定义N把直觉上值得试的方向列出来画个圈这个圈的大小就是你定义的N。这个圈不需要覆盖所有可能的操作因为真正值得花时间的候选本来就不是无限多的。另一种情况是N确实没法预先知道比如你在探查一个陌生系统的性能问题完全不知道可能的原因有几个。一个实用替代方案是滚动窗口法先拿近期查看过的原因列表当N按顺序计算37%基准线当前原因一旦越线就深挖。过一段时间如果没突破就把窗口往前滚动加入新发现的原因重新计算。这相当于把静态的37%策略变成了动态的自适应版本。我试过这个滚动窗口法处理线上偶发超时问题时效率很高。那种问题本质上原因池是开放的静态清单必然漏项滚动窗口能兼顾信息更新和决策效率。6. 我踩过的坑与一份自检清单理论说得再多不如实操教训来得深刻。这里我把在反复使用37%准则时踩过的坑、总结出的心得一次性列出来。6.1 常见误区三条第一个误区是把37%理解成只看前37%然后在后63%里选。这是理解偏差。正确的做法是前37%用来建立基准后63%用来执行越线即选的门槛规则。选中的那个人大概率落在后63%但前37%的作用是帮你知道好在哪而不是单纯被淘汰。第二个误区是卡精确的37%。我做过多次模拟测试30%到40%之间的成功率差距非常小。现实场景里你根本不需要去精算到小数点后两位。如果你非要纠结5个候选到底是取1个还是取2个选哪个都不会错太多真正错的是取到5个里的第4个还在观察。第三个误区是认为37%准则能帮你选到最优。它只能最大化选到最优的概率而且这个最大值只有37%左右。换句话说用这个策略你仍然有六成概率选不到全局最优。这一点非常反直觉但必须清醒它是一个决策框架用来在信息不足时定出一个理性可选的动作不是水晶球。6.2 一张速查表为了方便日常使用我把几种典型场景下的应用方式整理成了速查表场景N怎么定观察期做什么行动期触发条件慢SQL优化候选项列出的优化手段数量explain、行数估算、成本基线收益显著优于基线就深挖性能调优方案池可能的调参/改造方向数最小验证、压测快照方向收益超基准线1.5倍以上产品迭代候选功能需求池想法数量埋点/灰度/低成本验证转化指标明显超过观察组均值技术选型候选技术栈数量阅读架构文档、跑demo核心指标超越基准方案即可锁定候选人面试总面试人数前37%面试只做评价校准从后63%开始越线即推进这张表最大的作用是提醒我一句话任何一种优化都不是把手上资源全部砸进去而是花小钱买信息再集中火力打突破点。6.3 最后想分享的一个小技巧关于37%准则我最后的补充是一个使用小技巧它不只适用于一次决策也可以用在多轮滚动优化里。每完成一轮选型和投入就把新收集到的信息加入基准然后重新计算下一轮的37%观察窗口。这比一次性把所有选项铺开更贴合真实业务节奏因为很多优化问题本身就是不断有新信息流进来的过程。我还会把这个模型内化成一种日常思维方式当我在一个问题上花了超过三分之一的精力却还在收集信息时就会停下来问自己——我是不是该从探索模式切换为行动模式了这个问题问多了你会发现自己做决定的速度明显变快而且不再纠结。对我而言这就是37%准则在优化工作中最大的价值它不只是帮你选更好的方案还帮你在无限追求最优的焦虑里找到一个可以心安理得停下来的理由。