ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

胖头鱼的技术专栏-470 那条跑了半年的 SQL,怎么说慢就慢了(20260925)

胖头鱼的技术专栏-470 那条跑了半年的 SQL,怎么说慢就慢了(20260925) 数据库管理470期 2026-09-25胖头鱼的技术专栏-470 那条跑了半年的 SQL怎么说慢就慢了20260925一、优化器其实一直在猜二、那 10% 到底有多离谱三、那些年我们都是怎么熬的四、从巡检改成感应五、两个参数六、ANALYZE 不是免费的七、实操清单总结胖头鱼的技术专栏-470 那条跑了半年的 SQL怎么说慢就慢了20260925作者胖头鱼的鱼缸尹海文 Oracle ACE Pro: Database PostgreSQL ACE 10年数据库行业经验 拥有OCM 11g/12c/19c、MySQL 8.0 OCP、Exadata、CDP等认证 墨天轮MVPITPUB认证专家 圈内拥有“总监”称号非著名社恐社交恐怖分子 全网同名胖头鱼的鱼缸 ITPUByhw1809 除授权转载并标明出处外均为“非法”抄袭文章开始之前先祝大家中秋快乐正文开始一条跑了半年都好好的 SQL代码没动、索引没删、数据量也没爆——突然有一天慢了十倍。摊上这种事很多 DBA 第一反应多半是查锁、查 IO、查执行计划是不是变了。如果是计划确实变了可它凭什么变原因大概率是优化器手里那张地图是上个月的。最近翻金仓 KES V9 新版说明书V009R002C016在性能那一节扫到这么一句新增对表的增、删、改操作支持设置触发阈值当相应操作达到阈值时系统自动触发统计信息的即时更新功能保证业务在高并发、大数据量读写场景下优化器能够依据最新统计信息生成高效的执行计划。两行字很容易一扫而过。我盯着看了半天——这行字背后是数据库跟统计信息滞后这件事较劲的另一种解法。一、优化器其实一直在猜众所周知优化器不执行 SQL它只是估算——估算走索引能筛掉多少行、走全表扫描要读多少页、两个表谁当驱动表更划算然后挑一个它认为最便宜的方案。估算的依据是什么统计信息。表有多少行、某一列有多少个不同值、最常见的值是哪几个、数据分布偏不偏——这些不是每次执行时现算的那代价谁也付不起而是提前采样存好放在系统表里等着被查。问题就出在这儿它是提前存好的那就一定会过期。统计信息为什么没更新二、那 10% 到底有多离谱自动收集一直是后台进程在干规则一句话就能说完默认是50 reltuples × 0.1——累计改动超过表的 10%才考虑去更新统计信息。听着还行把数算出来看。改 99 万行优化器眼皮都不抬改 150 行它一天给你 analyze 好几回。偏偏大表又是最经不起烂计划的——小表走错计划顶多多花几十毫秒大表走错就是几百秒。还有第二个坑跟比例无关跟时机有关。后台进程是轮询的默认一分钟醒一次看看有没有活儿。醒了之后还不立马干——能同时干活的进程就那么几个一堆表排着队等。遇到批量导入、月末结算这种场景几十上百张表同时超线排队能排到几十分钟之后。图上那条 35 分钟的滞后窗口就是这么攒出来的。三、那些年我们都是怎么熬的道理不复杂真干起来是另一回事。这些年老办法攒了三条一条比一条有味道。第一条手工补一刀。批量导入脚本的最后加一句ANALYZE 表名;——简单粗暴确实管用毛病是靠人记换个人写脚本就忘了。第二条挂定时任务。cron 里半夜跑一轮核心表过一遍。忘的问题解决了但它是无差别的——昨天一行没变的表也照跑白扔 IO。第三条把比例调小。触发线从 10% 降到 1%大表好受点了小表更疯了而且该等轮询还是得等轮询。四、从巡检改成感应V009R002C016 给的这个能力跟上面三条路子都不一样——它不在什么时候去查上做文章而是让变更自己报上来。说白了你在表上装个计数器说好累计变动够 N 行就吱一声DML 一执行完当场数数够了就立即触发 ANALYZE。老机制是一锅烩新机制能把增、删、改分开对待只增不改的流水表只管 INSERT 就行每天批量清过期数据的表DELETE 才是主角。还有一点别忘了——这套东西默认是关的装上不生效。为什么不给默认开着往下看。五、两个参数这两个参数是配合干活的——光开一个没用这点特别容易踩。参数一data_analyze_threshold表级阈值给指定的表设一个行数门槛对该表的 DML 累计超过这个数且对应类型的开关开着就立即触发统计信息更新。支持的类型有 INSERT、DELETE、UPDATE、COPY、sysbulkload 五种用ALTER TABLE按表设置。默认 0 就是不启用——这个值不设后面一切免谈。参数二auto_analyze全局开关决定哪一类操作会触发统计信息更新实例级设置八种模式见下图可以组合着写。还有一层结构上的事阈值是表级的开关是实例级的。开关决定这个库管不管 INSERT阈值决定这张表攒够多少行算一次。同一套开关下核心交易表可以设 5 万日志表可以设 50 万配置表干脆不设——粒度是分开的这正是它比调全局比例精细的地方。六、ANALYZE 不是免费的这么好用的能力为什么默认不给开着因为每次触发都是一次 ANALYZE而 ANALYZE 是要花钱的——它得真刀真枪去采样吃 CPU 也吃 IO。设小了是风暴设大了白开这个度怎么把握看下图。具体到一张表可以先问三个问题这张表一天变多少行查sys_stat_user_tables里的n_mod_since_analyze就能估出来这些变更集中还是分散批量导入的阈值就贴着单次批量量级设匀速写入的按期望几小时更新一次倒推这张表的查询对行数敏不敏感大表关联、范围扫描、聚合——敏感值得设按主键点查的统计信息差一点无所谓不用凑热闹。分区表要多想一步阈值是表级的主表和子表得分别想清楚。七、实操清单本期跟随总监把要用的 SQL 摆出来。这套环境我还没装先把清单放这儿——等装好跑一遍再补实测回显。你着急的话直接拿去用也行。1. 看参数现在都是什么值SELECTname,setting,unit,boot_val,reset_val,min_val,max_val,contextFROMsys_settingsWHEREnameIN(auto_analyze,data_analyze_threshold,autovacuum_analyze_threshold,autovacuum_analyze_scale_factor,default_statistics_target)ORDERBYname;重点看auto_analyze是不是空的、data_analyze_threshold是不是 0。2. 开开关实例级ALTERSYSTEMSETauto_analyzeinsert_on,update_on;SELECTsys_reload_conf();3. 给具体的表设阈值表级ALTERTABLE订单表SET(data_analyze_threshold50000);4. 确认设没设上SELECTrelname,reloptionsFROMsys_classWHERErelname订单表;reloptions里能看到data_analyze_threshold50000就算落住了。总结统计信息自动更新触发阈值有个特别的地方它把调参的主动权从表有多大手里交回到了你想要多新鲜手里。所以我的建议别一把全开。默认关着是有道理的先查n_mod_since_analyze找出真正落后的那几张表针对性设阈值宁大勿小。保守起步观察一段时间触发频率再往下调。ANALYZE 风暴比统计信息滞后难收拾得多老机制别撤。自动收集还在跑着它管的是全库兜底和死元组回收新机制是在它之上加的精准补充不是替代品把n_mod_since_analyze加进日常巡检。这个指标以前只是参考值现在它是你判断哪张表该装计数器的直接依据。回到开头那条跑了半年突然变慢的 SQL。它慢不是因为优化器变笨了——优化器一直那么聪明也一直那么相信它手里的地图。问题从来都是地图是上一版的路已经修过了。这次的更新做的是一件挺朴素的事给表装个计数器路一修完就通知画图的人。老规矩知道写了些啥。
返回列表