等待问题
等待问题一般分为几大类
- 系统资源不足
- 任务优先级不高
- 磁盘慢
常见等待的问题原因
- 同时并行任务太多,系统资源不足,造成等待
- 出现慢盘,分布式系统中每天机器的性能有差异
- 数据量比较大(超过1亿数据会比较慢),数据膨胀或者慢udf
常见处理方案
- 调整任务优先级
- 更改上游依赖, 可以依赖已经产出的任务,比如T-2的方式
- 慢盘问题,可能是重跑能够解决
长尾问题
长尾问题一般分为下面几类
- Map过程长尾
- Reduce过程长尾
- Join过程长尾
- Merge过程长尾
Map(一般是select语句)过程长尾
- 常见的Maori端长尾原因
- 某些Map Instance 读取的文件数,字节数比其他的Map instance 多很多
- 某些Map instance 读取的时间要比其他Map Instance多很多
- 常见的Map端长尾处理方法
- 数据过滤,加分区或者过滤条件
- 分而治之使用union all将大表分多次读取合并。(比如: 读取最近三个月的数据,分3个union all 每次读取一个月的数据)
- 通过合理调整odps.sql.mapper.split.size参数,来控制Map Instance个数(可能会导致输出小文件变多)
Reduce过程边长
- 常见reduce端长尾原因
分发键分部不均匀,存在热点数据(一个instance处理记录超过1亿条,处理性能就会下降) - 常见reduce端长尾处理方法
- count(distinct col)可以转化成两次group by分多次汇总数据。
distinct只能拿到所有的数据再去重。这样所有的数据在一个inctance处理
- 脏数据过滤(比如: 业务上是否考虑将null数据进行过滤)
Join过程长尾
- 常见的Join过程长尾原因
分发键(关键键)分部不均匀。本质山是非主键关联 - 常见Join过程长尾处理方法
- 关联之前要对关联键去重,尽可能主键关联,避免非主键关联
- 关键键类型一致。比如: buyer_id 和visitor_id 关联,一个是bigint另外一个是string 类型。会强转为double类型,导致很多string类型转为null
- 大表和小表,mapjoin(map的性能要好于Join的性能,本质上是Join端任务放在map端执行)
开发技巧
选表原则
- 看数据量
- 小表原则,选择满足需求的小表,比如汇总表
- 时时表尽量选择增量表
- 看产出时间
- 选择产出早的表
- 依赖的N个上游表,尽量保证上游的产出时间均匀
模型设计原则
- 抽取公共表
- 公共表要独立出来,比如常用粒度轻度汇总表
- 表设计成分区
- 产出链路短
- 节点依赖层次尽可能少,链路要短
代码开发原则
过滤再计算
- 分区过滤, 有效值过滤
- 汇总后再关联,避免明细关联。多使用轻度汇总表
开发技巧使用
- 少使用count distinct
- 使用系统udf代替自己写的udf
调度原则
设置高优先级
- 叶子节点设置高优先级,优先级会自动上推到上游节点
跨天依赖
- 变化不大的表,可以考虑跨天依赖
- 依赖的max_pt要排除当天依赖
SQL 优化的本质
本质是不同Task的灵活处理。
- 其中Map Task 性能> Reduce 性能 > join性能
- 减少某些task,比如mapjoin,减少join task 本质上是减少网络芬达,降低网络IO开销