订阅更新

分区策略深度指南

数仓建模手册 第 13 题 约 4 分钟读完

本文目录
  1. 总结
  2. 分区到底解决什么问题?
  3. 分区设计三原则
  4. 动态分区 vs 静态分区
  5. 分区与小文件问题

总结

记忆点内容
分区本质物理拆分数据,查询时跳过无关目录
选键原则按查询模式选,最常WHERE的字段
数量控制单表分区控制在1万以内
动态分区批量写入方便,但要设上限防爆炸
小文件分区过细的副产品,要定期合并

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

进阶 | 大数据面试 · 数仓建模系列

面试真题
你们数仓表的分区是怎么设计的?有没有遇到过分区相关的性能问题?

分区到底解决什么问题?

大数据表动辄几十亿行,如果每次查询都全表扫描,再好的集群也扛不住。分区的本质就是物理上把数据拆成不同的目录,查询时只读需要的目录,跳过其他的——这就是「分区裁剪」。没有分区扫描全部365天1000亿行;有dt分区后只扫描当天约3亿行,性能差距100倍以上。

Wood的实战经验
我接手过一个项目,有张核心表建的时候没做分区,每天全量扫描跑了4个小时。加了dt分区之后同样的逻辑只要8分钟。分区设计是最基本但也是收益最高的优化手段。

分区设计三原则

原则一:按查询模式选分区键

分区键要选WHERE条件里最常出现的字段。大部分业务表用dt(日期),出海业务加region,多业务线共用表加biz_type。反面教材:用user_id做分区,用户量几千万,分区数爆炸,HDFS NameNode元数据压力直接打满。

原则二:分区数量要可控

经验值:单表分区数控制在1万以内。dt分区一天一个一年365个✔;dt+region 10×365=3650个✔;dt+hour+city 365×24×500=438万个✖。分区太多导致小文件泛滥、NameNode压力大、元数据查询慢。

原则三:分区键数据类型用STRING

推荐dt STRING,不推荐dt DATE。不同引擎对DATE类型行为不一致,STRING灵活且无精度问题。

动态分区 vs 静态分区

静态分区手动指定目标分区,确定性强,适合日常调度。动态分区自动识别写入哪个分区,适合回刷历史,但可能产生大量小分区。

Wood的实战经验
我有一次用动态分区回刷历史数据,没设上限,一口气创建了5万个分区,NameNode直接告警。后来加了`SET hive.exec.max.dynamic.partitions=2000;`做安全兜底。教训:动态分区好用但一定要设上限。

分区与小文件问题

分区设计不当最容易引发小文件问题。比如每小时一个分区,每个分区只有几MB,HDFS上堆了几十万个小文件。危害:NameNode内存压力、Map任务数暴增、下游读取性能差。解决方案:写入时合并(SET hive.merge.mapredfiles=true)、用DISTRIBUTE BY控制输出文件数、定期合并。

Wood的实战经验
我们团队的规范是:每个分区的文件数不超过分区大小/128MB,比如分区有1GB数据就控制在8-10个文件左右。出海业务还会加region分区,方便按地区管理数据生命周期。
面试加分提示
「我们核心事实表用dt做一级分区,出海业务加了region二级分区。99%的SQL都有dt和region条件,分区裁剪效果很好。遇到过一次小文件问题:实时任务每小时写一次,HDFS上积累了大量小文件。后来加了每日合并调度任务,NameNode压力下降了60%。」
刷题进度保存在当前浏览器