资讯动态

直方图适用于哪些倾斜数据——状态与地区字段的分布分析、统计对象选择与执行计划验证

发布时间:2026/8/25 14:15:43 来源:尧图企业网站定制
文章目录每日一句正能量1. 背景与问题有数据倾斜就加直方图这其实只说对了一半2. 环境与数据状态字段和地区字段恰好代表两种不同的倾斜模型2.1 状态字段低基数 极端热点2.2 地区字段头部集中 大量长尾2.3 为什么直方图特别适合“有顺序的剩余值域”2.4 纯分类值很少时直方图价值可能很低3. 复现过程默认统计为何低估一个长尾地区40倍3.1 先看真实分布不要先看执行计划3.2 查看 sys_stats3.3 默认统计目标下R087没有进入MCV3.4 普通 ANALYZE 后为什么只能改善一部分4. 方案实施MCV、Histogram、n_distinct与扩展统计应该如何分工4.1 第一原则热点值优先看MCV4.2 第二原则长尾范围分布看Histogram4.3 第三原则高基数热点字段需要 MCV n_distinct4.4 第四原则日期/金额等范围查询更依赖Histogram4.5 第五原则追加型日期还要看correlation4.6 第六原则提高列级统计目标而不是先全局调大4.7 提高统计目标带来的是什么4.8 为什么不能全局 default_statistics_target10004.9 status region为什么单列统计仍会失效4.10 多列相关性需要扩展统计4.11 CREATE STATISTICS后必须ANALYZE4.12 不要把Histogram当成热点名单4.13 直方图不适合没有顺序操作符的数据类型5. 结果对比统计目标提高后长尾地区估算从40倍误差降到1.1倍E0默认/旧统计E1普通 ANALYZEE2region统计目标500E3statusACTIVEE4status region扩展统计5.1 汇总5.2 直方图真正解决的是“非热点区间”问题5.3 Buffer Read也同步变化5.4 普通值、热点值、长尾值必须分开验收5.5 统计越准不代表所有参数都用同一个计划6. 风险与复盘直方图最容易被误用成“所有倾斜问题的万能药”6.1 风险一低基数状态字段盲目追求Histogram6.2 风险二只提高全局统计目标6.3 风险三只看Histogram不看MCV6.4 风险四单列统计解决不了组合倾斜6.5 风险五统计采样不是绝对精确6.6 风险六数据分布变化后统计重新过期6.7 风险七相关性与直方图混淆推荐统计对象选择表推荐诊断顺序回退方案最终复盘附录 A查看统计分布附录 B提高地区统计目标附录 C状态地区扩展统计附录 D最低验收门禁每日一句正能量用琐碎编织温暖用平淡注解浪漫。相遇了就好好珍惜吧。用琐碎编织温暖用平淡注解浪漫。最奢侈的拥有不过是——能和你一起幸福地看一次月升月落。主题数据倾斜 / 直方图 / 状态与地区字段重点MCV、Histogram、n_distinct、correlation、default_statistics_target、列级统计目标、扩展统计、执行计划与参数验证适用场景KingbaseES 中状态、地区、租户、日期、业务类型等分布明显不均匀的过滤列尤其适用于“同一列不同值执行计划完全不同”的生产问题。1. 背景与问题有数据倾斜就加直方图这其实只说对了一半数据库性能文章里经常有一句话数据倾斜严重 → 建立直方图方向没有错。但如果真正把这个结论用于生产会发现一个问题不同类型的数据倾斜真正起作用的统计对象并不一样。例如状态字段ACTIVE 95% CLOSED 3% FROZEN 0.1% 其他 1.9%这里只有几个离散值而且ACTIVE几乎占全部数据。这时优化器最需要知道的不是ACTIVE在整个排序区间里的位置而是ACTIVE到底占95%真正重要的是Most Common Values Most Common Frequencies也就是 MCV。再看地区字段EAST 35% SOUTH 20% NORTH 15% WEST 8% ... R087 0.03% R088 0.02%它可能有几百个地区编码头部明显集中。剩余还有大量长尾地区这种字段MCV Histogram往往都很有价值。KingbaseES 官方系统统计视图文档明确给出了单列统计中的几个核心字段most_common_vals most_common_freqs histogram_bounds n_distinct correlation其中非常重要的一点是如果一个值已经进入most_common_vals它会从直方图计算中排除。也就是说MCV负责准确描述特别常见的热点值而Histogram主要刻画除MCV之外的剩余值如何分布所以“直方图适合什么倾斜数据”的真正答案并不是倾斜就用直方图而是先把热点值、长尾值、值域、distinct 数和多列相关性分开再决定 MCV、Histogram、n_distinct 或扩展统计各自承担什么角色。2. 环境与数据状态字段和地区字段恰好代表两种不同的倾斜模型示例表CREATETABLEcustomer_event(event_idBIGINTPRIMARYKEY,customer_idBIGINTNOTNULL,statusVARCHAR(20)NOTNULL,region_codeVARCHAR(20)NOTNULL,tenant_idBIGINTNOTNULL,event_dateDATENOTNULL,amountNUMERIC(18,2));数据总行数 1亿 status 5个值 region_code 300个值 tenant_id 20万 event_date 持续追加2.1 状态字段低基数 极端热点真实分布ACTIVE 95% CLOSED 3% PENDING 1% FROZEN 0.1% 其他 0.9%查询WHEREstatusACTIVE和WHEREstatusFROZEN虽然只是参数不同但成本完全不同。对于ACTIVE返回9500万索引扫描未必是好选择。对于FROZEN只返回10万索引可能非常合适。如果优化器把5个状态简单平均成每个20%两边都会估错。这类问题最适合MCV直接保存ACTIVE0.95 CLOSED0.03 ...而不是依赖普通直方图区间猜测。2.2 地区字段头部集中 大量长尾地区EAST 35% SOUTH 20% NORTH 15%这些头部值应该进入MCV而剩余几百个低频地区可以由Histogram帮助估计。这就是一个典型MCV负责头部 Histogram负责尾部的字段。2.3 为什么直方图特别适合“有顺序的剩余值域”histogram_bounds本质上是把非 MCV 值按大小顺序划分为近似等频区间。所以日期 金额 地区编码 连续ID等具有可比较顺序的类型直方图特别有意义。例如WHEREamountBETWEEN1000AND5000或者WHEREevent_dateDATE2026-07-01优化器可以利用直方图估这个区间大约占多少数据2.4 纯分类值很少时直方图价值可能很低如果status只有5个值而这5个值全部进入most_common_vals那么histogram_bounds可能为空。官方系统视图文档明确说明如果most_common_vals等于整个值集合直方图列可以为空。这不是统计异常。而是说明这个字段已经被 MCV 足够完整地描述不需要再用直方图描述剩余值。3. 复现过程默认统计为何低估一个长尾地区40倍3.1 先看真实分布不要先看执行计划第一步SELECTregion_code,COUNT(*)cntFROMcustomer_eventGROUPBYregion_codeORDERBYcntDESC;得到EAST 3500万 SOUTH 2000万 NORTH 1500万 ... R087 48万 R091 2万 ...然后状态SELECTstatus,COUNT(*)FROMcustomer_eventGROUPBYstatus;先建立数据真实世界再看优化器世界。3.2 查看 sys_statsSELECTattname,null_frac,n_distinct,most_common_vals,most_common_freqs,histogram_bounds,correlationFROMsys_statsWHEREtablenamecustomer_event;KingbaseES 官方sys_stats文档对这些字段定义非常清楚most_common_vals最常用值most_common_freqs对应频率histogram_bounds除去 MCV 后剩余值的近似等频分界n_distinct不同值数量估计correlation物理行顺序和逻辑值顺序之间的相关性。3.3 默认统计目标下R087没有进入MCV假设default_statistics_target100采样后EAST SOUTH NORTH ...进入 MCV。但R087没有。它只能通过Histogram 剩余distinct平均估算。计划EXPLAIN(ANALYZE,BUFFERS,VERBOSE)SELECT*FROMcustomer_eventWHEREregion_codeR087;示例estimated: 12,000 actual: 480,000偏差40倍优化器认为只返回1.2万行于是可能选择Index Scan实际访问48万大量随机读。P959.8s3.4 普通 ANALYZE 后为什么只能改善一部分执行ANALYZEcustomer_event;新的随机样本可能更好捕捉到地区分布示例estimated: 21万 actual: 48万 P95: 5.4s明显改善。但还是偏差较大。原因是默认采样量和统计条目仍然有限。这时才有理由提高列级统计目标4. 方案实施MCV、Histogram、n_distinct与扩展统计应该如何分工4.1 第一原则热点值优先看MCV状态ACTIVE95%最重要的是ACTIVE是否进入MCV 频率是否接近0.95如果most_common_vals已经包含全部状态值那么直方图为空完全正常。因此低基数、极端头部集中字段核心统计对象是 MCV不是 Histogram。4.2 第二原则长尾范围分布看Histogram地区有300个值MCV可能只记录头部几十/上百个剩余值由Histogram描述如果查询经常访问非头部地区就需要保证直方图有足够粒度。4.3 第三原则高基数热点字段需要 MCV n_distinct租户20万个大部分很小几个超级租户占40%这类字段MCV用来描述超级租户。n_distinct用来描述剩余高基数长尾。只看直方图不够4.4 第四原则日期/金额等范围查询更依赖Histogram例如WHEREevent_date2026-07-01优化器需要估计日期区间占比Histogram非常适合。金额WHEREamountBETWEEN1000AND10000也是类似。4.5 第五原则追加型日期还要看correlation如果表按时间持续追加event_date和磁盘物理顺序高度相关correlation可能接近1KingbaseES 官方 sys_stats 文档指出当 correlation 接近-1 或 1索引扫描对应的随机访问成本会更低因为值顺序和物理顺序更相关。所以范围查询成本不能只看Histogram选择率还要看correlation4.6 第六原则提高列级统计目标而不是先全局调大例如ALTERTABLEcustomer_eventALTERCOLUMNregion_codeSETSTATISTICS500;状态ALTERCOLUMNstatusSETSTATISTICS300;然后ANALYZEcustomer_event;官方文档说明数组统计条目的最大数量可以通过ALTER TABLE ... SET STATISTICS按列控制也可以通过default_statistics_target全局控制。工程上优先列级因为只对真正倾斜、真正影响计划的列增加成本。4.7 提高统计目标带来的是什么目标提高后采样量增加 MCV可记录更多值 Histogram桶更多因此R087可能直接进入MCV或者落入更精细的Histogram区间示例estimated: 44万 actual: 48万P952.6s4.8 为什么不能全局 default_statistics_target1000KingbaseES 官方统计文档说明default_statistics_target会影响采样容量和统计信息量。目标越高ANALYZE时间增加 采样更多 统计目录更大 规划时读取统计的成本也可能增加所以全局1000并不是免费午餐。4.9 status region为什么单列统计仍会失效假设EAST地区 ACTIVE99% 其他地区 ACTIVE65%查询WHEREstatusACTIVEANDregion_codeEAST单列统计知道ACTIVE95% EAST35%如果近似独立0.95 × 0.35 ≈33.25%实际34%差距不算大。但换成FROZEN EAST可能FROZEN总体0.1% EAST中实际上几乎为0单列独立假设就可能严重错误。4.10 多列相关性需要扩展统计创建CREATESTATISTICSst_event_status_region(dependencies,ndistinct,mcv)ONstatus,region_codeFROMcustomer_event;然后ANALYZEcustomer_event;KingbaseES 官方CREATE STATISTICS文档支持ndistinct dependencies mcv三类扩展统计。其中多列MCV可以直接保存(status, region)常见组合频率。dependencies描述列之间的函数依赖程度ndistinct描述列组合的不同值数量4.11 CREATE STATISTICS后必须ANALYZE这一点很容易漏。创建统计对象不等于统计数据已经采集官方系统目录文档明确说明扩展统计实际数据是在ANALYZE时填入相应统计目录。所以CREATE STATISTICS → ANALYZE必须成对。4.12 不要把Histogram当成热点名单直方图的职责不是列出每个值的频率它是对非MCV剩余值的有序分布做分桶所以排查热点参数优先看most_common_vals排查范围/长尾区间再看histogram_bounds4.13 直方图不适合没有顺序操作符的数据类型官方 sys_stats 文档指出如果类型没有 操作符直方图可能为空。这也是直方图的数学性质决定的它必须能定义“前后区间”不能对所有类型强求。5. 结果对比统计目标提高后长尾地区估算从40倍误差降到1.1倍E0默认/旧统计regionR087 estimated: 1.2万 actual: 48万 Plan: Index Scan P95: 9.8sE1普通 ANALYZEestimated: 21万 actual: 48万 Plan: Bitmap Scan P95: 5.4sE2region统计目标500estimated: 44万 actual: 48万 P95: 2.6s偏差约1.09倍这时已经足以让扫描方式更稳定。E3statusACTIVE默认如果错误平均20%实际95%计划很可能倾向Index ScanMCV准确后estimated≈9500万优化器自然更倾向Bitmap/Seq Scan示例P951.9s这里真正起作用的是MCV不是直方图。E4status region扩展统计组合查询statusACTIVEANDregion_codeEAST普通单列统计estimated存在明显组合偏差扩展 MCV/dependencies 后estimated≈3370万 actual≈3400万Join 顺序和 Scan更稳定P951.5s5.1 汇总实验条件统计策略EstimatedActualP95E0R087默认旧统计1.2万48万9.8sE1R087ANALYZE21万48万5.4sE2R087target50044万48万2.6sE3ACTIVEMCV增强9460万9500万1.9sE4ACTIVEEAST扩展统计3370万3400万1.5s以上为方法演示数据不是生产实测。5.2 直方图真正解决的是“非热点区间”问题这张表最值得注意ACTIVE性能改善主要来自MCV而R087作为地区长尾值改善更多依赖更细的MCV/Histogram分布所以文章标题虽然是直方图适用于哪些倾斜数据但真正答案必须包括什么时候不应该把问题归给直方图5.3 Buffer Read也同步变化R087旧计划 360万Buffers 新计划 75万说明计划确实减少了数据库访问工作量而不是单次碰巧缓存更热5.4 普通值、热点值、长尾值必须分开验收只测试EAST无法证明R087的估算质量。只测试ACTIVE无法证明FROZEN的计划。所以最低参数组Top1热点 Top5普通 长尾 极稀有必须分别测。5.5 统计越准不代表所有参数都用同一个计划这反而是正确现象。例如ACTIVE95%Seq ScanFROZEN0.1%可能Index Scan如果参数敏感场景使用计划缓存还要结合上一篇Custom Plan / Generic Plan一起验证。6. 风险与复盘直方图最容易被误用成“所有倾斜问题的万能药”6.1 风险一低基数状态字段盲目追求Histogram只有5个状态全部已进入 MCV。Histogram为空完全可能是正确状态。6.2 风险二只提高全局统计目标全库1000可能ANALYZE显著变慢 统计目录膨胀而真正需要的只有5个热点列所以优先列级。6.3 风险三只看Histogram不看MCV热点数据EAST35%如果已经进入 MCV它本来就不应该出现在histogram_bounds中不要误判直方图缺少EAST 统计不完整6.4 风险四单列统计解决不了组合倾斜status很准。region也很准。但status region仍然可能错。需要扩展统计6.5 风险五统计采样不是绝对精确即使 target 提高也只是更大的样本不是全表精确统计。目标应是误差不再跨越计划成本边界而不是estimatedactual 每条都完全一样6.6 风险六数据分布变化后统计重新过期今天EAST35%下季度业务调整EAST60%之前精确的 MCV 也会过期。所以仍然需要ANALYZE新鲜度治理和上一篇文章形成闭环。6.7 风险七相关性与直方图混淆correlation描述物理顺序与逻辑值顺序不是两列之间的业务相关性多列业务相关要看extended statistics dependencies两个“相关”概念不能混为一谈。推荐统计对象选择表低基数极热点字段 → MCV 头部热点 长尾值域 → MCV Histogram 高基数超级热点 → MCV n_distinct 范围字段 → Histogram 追加型范围字段 → Histogram correlation 多列相关 → Extended MCV / dependencies / ndistinct推荐诊断顺序1. 真实GROUP BY分布 2. 看most_common_vals/freqs 3. 看histogram_bounds 4. 看n_distinct/null_frac 5. 热点/普通/长尾分别EXPLAIN ANALYZE 6. 对比estimated/actual 7. 列级SET STATISTICS 8. ANALYZE 9. 多列相关则CREATE STATISTICS 10. 再ANALYZE和计划回归回退方案如果提高统计目标或建立扩展统计后出现计划回归1. 保存前后sys_stats 2. 保存前后EXPLAIN ANALYZE 3. 不要直接删除所有新统计 4. 如果target过高恢复原列级target后重新ANALYZE 5. 如果扩展统计确有负面作用记录证据后DROP 6. 再次ANALYZE 7. 重测热点/普通/长尾/组合参数统计回退必须单变量不要同时改SQL 删索引 禁用Join否则无法证明根因。最终复盘“直方图适用于哪些倾斜数据”的最准确答案是直方图适合描述 非MCV值的有序分布和范围选择性但热点值优先由 MCV 描述。高基数还要看 n_distinct。追加型范围列还要看 correlation。多列相关必须看扩展统计。如果只记住一句话数据倾斜调优不是“给列加直方图”而是先判断倾斜属于热点值、长尾范围、高基数还是多列相关再让 MCV、Histogram、n_distinct 和扩展统计各自承担它最擅长的那部分估算。只有这样统计信息才真正服务于正确的基数估算 → 正确的Scan → 正确的Join → 稳定的P95/P99而不是为了“统计对象看起来更丰富”而收集统计。附录 A查看统计分布SELECTattname,n_distinct,most_common_vals,most_common_freqs,histogram_bounds,correlationFROMsys_statsWHEREtablenamecustomer_event;附录 B提高地区统计目标ALTERTABLEcustomer_eventALTERCOLUMNregion_codeSETSTATISTICS500;ANALYZEcustomer_event;附录 C状态地区扩展统计CREATESTATISTICSst_event_status_region(dependencies,ndistinct,mcv)ONstatus,region_codeFROMcustomer_event;ANALYZEcustomer_event;附录 D最低验收门禁[ ] 热点值真实占比已采集 [ ] 长尾值已抽样 [ ] MCV与频率已检查 [ ] Histogram已检查 [ ] n_distinct已检查 [ ] correlation含义已确认 [ ] 热点/普通/长尾计划已验证 [ ] estimated/actual在预算内 [ ] 列级target有依据 [ ] 扩展统计仅用于相关列 [ ] ANALYZE成本可接受 [ ] P95/P99达到SLA [ ] 回退参数已保存转载自https://blog.csdn.net/u014727709/article/details/163950341欢迎 点赞✍评论⭐收藏欢迎指正

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价