分区策略深度指南
总结
| 记忆点 | 内容 |
|---|---|
| 分区本质 | 物理拆分数据,查询时跳过无关目录 |
| 选键原则 | 按查询模式选,最常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%。」 |
|---|