一次问答的链路测量手记 · 从 38 秒到 4 秒01周一早上那三十秒周一早上八点四十运营总监在群里丢了句话上周租金收缴率怎么掉这么多。小周打开问数平台把这句话原样敲进去按回车。转圈。转了很久。她看一眼手机又看回屏幕然后关掉页面翻出上个月那份还没删的旧报表。这个动作我记了很久。报表本身没什么问题问题在我们费了半年力气做到能用一句话查数结果败在等三十秒上。后来我拿这件事做了两个月把一次问数的耗时从头到尾量了一遍。这篇写这个。02先记秒数别猜第一版做了件很笨的事给链路每一段打点。一次问数走五段路。听懂问题含分词、实体识别、时间归一化「上周」到底指哪七天的哪一天开始。找表找字段从两百多张表里筛出可能相关的几张。拼 SQL 是模型干活。执行是数据库干活。收尾出图出文由前端和模板管。打点跑了三天抓了两千多次问答。结果第一眼就把我的判断推翻了。我一直以为慢在模型上那东西听着就贵。实测里模型那段平均 3.1 秒数据库那段平均 26 秒。38 秒的总耗时七成耗在数据库。模型背了锅。我后来想过为什么会误判。大模型是黑盒等它的时候屏幕什么也不动人容易把等待感全记到它头上。数据库在后台扫几百万行你看不见也想不到。看不见的地方最藏问题性能上尤其明显。0326 秒是怎么来的那段时间我干的事基本是跟在每条慢查询后面捡东西。捡出三类。索引被自己废掉。合同表的起租日期上有索引模型生成的 SQL 写成to_char(起租日期,YYYY-MM) 2026-10字段被函数包了一层索引用不上只能全表扫。这种写法在自然语言转 SQL 里到处都是因为用户说的就是十月模型顺手把日期格式化了。分区裁剪失效。我们按年做了分区条件被 cast 过优化器识别不出该走哪个分区每次扫全部。join 得太多。问一句这栋楼租金收了多少模型会老实关联合同、房源、租户、收款四张表。前两张必要后两张只为了显示名字。三类叠起来「上周收缴率」这句看起来很简单的问话扫了四百多万行。改法很朴素。日期条件换成开区间起租日期 月初 and 起租日期 下月初函数挪到常量那边。分区字段单抽一列存年份别在查询里算。join 按需生成用户问了租户名才带租户表。光这三条26 秒掉到 9 秒。04宽表和宽表带来的新麻烦剩下 9 秒靠改 SQL 压不下去了它本来就要扫那么多明细。我们加了一层日粒度汇总表。收缴率、出租率、单方能耗、在租面积这几类最常被问的指标每天凌晨算一遍落表一行是一栋楼一天。查询进来先判断能不能命中汇总表能命中就不碰明细。9 秒变成 2.6 秒。汇总表有代价代价在口径。明细算收缴率和汇总算收缴率中间差一个「当月应收到期日已过」的过滤条件写汇总作业的同事漏了。上线第三天财务发现平台给的收缴率和他们自己算的对不上差两个点。账算清楚就明白了多加一层计算就多一个口径要守。我们后来把每个汇总指标的取数逻辑写进配置文件和明细口径并排放改一个必须同时改另一个评审时一起看。05缓存三个 key 少一个就出事再往下压只能靠缓存。高频问题命中直接返回这是最省事的一招。P50 从 2.6 秒掉到 400 毫秒。然后就出事了。数字过期。缓存 key 当时只用问题原文没带时间参数。运营早上问这个月出租率下午再问拿到早上的旧数。上午刚签了份合同数字该变页面没变。越权。两个人问同一句话结果该不一样数据范围不同。key 里没带权限A 的答案给了 B。口径切换。中途调整过一次收缴率的分母缓存里的旧结果还在新旧两套数混着返回。三次事故之后key 定成三段拼起来归一化后的问题、时间窗口、权限范围。少一段都不行。有个取舍要说清。带上权限之后命中率掉了差不多一半它变成了按人区分的缓存。拿命中率换正确性这笔账我觉得不用犹豫。06四秒之后她说还是慢数字压到 4.2 秒我挺得意专门跑去找小周演示。她试了两次说还是有点慢。我有点不服四秒还慢。后来让她一边操作一边说感受才明白问题在哪。等四秒和等四秒不一样。一种屏幕什么都不动你不知道它在干嘛。一种上面一行小字在跳正在查十二万条合同已经找到三百八十六条你会觉得它在干活。差别在进度秒数只是背景。后面做的事没什么技术含量。中间状态吐出来。先出结论那一句和总数明细后补。SQL 执行超过两秒先显示正在查询预计还需两秒。图表不等明细全量先画前一百条。同一套后端改完这些小周的原话是现在感觉挺快的。07现在的做法我们没再追更低的数字。P95 稳在六秒上下偶尔遇到跨年的大范围问题会冲到十几秒这个我认。每月看一次 P95 和慢查询 Top20掉队的拉出来单独看。超过八秒才立项其余记账不动。优化到四秒花了我两个月四秒到三秒可能要再花两个月那一秒用户感觉不到。工程上容易犯的错是把能优化的都优化一遍忘了问一句值不值。上周我又看见小周在那个页面敲字。这次她敲完没关页面等着屏幕上那行小字在跳。大概三秒表格出来了。文中所涉数据来自一次真实的链路打点跑了三天两千多次问答。数字做了取整处理。
阅读完成 · 觉得有帮助?