欢迎点击此处关注公众号。
问了一些细节。
Hive 的基本流程:
UI 调用 DRIVER 的接口;
DRIVER 为查询创建会话句柄,并将查询发送到 COMPILER 生成执行计划;
COMPILER 从元数据存储中获取本次查询所需要的元数据,该元数据用于对查询树中的表达式进行类型检查,以及基于查询谓词修建分区;
COMPILER 生成的计划是分阶段的 DAG,每个阶段要么是 map/reduce 作业,要么是一个元数据或者 HDFS 上的操作。将生成的计划发给 DRIVER。如果是 map/reduce 作业,该计划包括 map operator trees 和一个 reduce operator tree,执行引擎将会把这些作业发送给 MapReduce。
执行引擎将这些阶段提交给适当的组件。在每个 task(mapper/reducer) 中,从 HDFS 文件中读取与表或中间输出相关联的数据,并通过相关算子树传递这些数据。最终这些数据通过序列化器写入到一个临时 HDFS 文件中(如果不需要 reduce 阶段,则在 map 中操作)。临时文件用于向计划中后面的 map/reduce 阶段提供数据。
最终的临时文件将移动到表的位置,确保不读取脏数据(文件重命名在 HDFS 中是原子操作)。对于用户的查询,临时文件的内容由执行引擎直接从 HDFS 读取,然后通过 Driver 发送到 UI。
编译 SQL 的任务是在上述的 COMPILER(编译器组件)中完成的。Hive 将 SQL 转化为 MapReduce 任务,整个编译过程分为六个阶段:
其中重点是第 5 点生成物理执行计划。举例说明:
例 1 join on:
select u.name, o.orderid
from order o
join user u on o.uid = u.uid;
关于 join:在 map 的输出 value 中为不同表的数据打上 tag 标记,在 reduce 阶段根据 tag 判断数据来源。
关于 on:on 后面的字段就是 key,shuffle 的时候相同的 key 会进入同一个 reducer 中。
最后同一个 reduce 中 tag 不同的进行组合即可。
例 2 Group By:
select rank, isonline, count(*)
from city
group by rank, isonline;
将 Group By 的字段组合为 map 的输出 key 值,利用 MapReduce 的排序,在 reduce 阶段保存 LastKey 区分不同的 key。MapReduce 的过程如下:
例 3 Distinct:
select dealid, count(distinct uid) num
from order
group by dealid;
当只有一个 distinct 字段时,如果不考虑 Map 阶段的 Hash Group By,只需要将 Group By 字段和 Distinct 字段组合为 map 输出 key,利用 mapreduce 的排序,同时将 Group By 字段作为 reduce 的 key,在 reduce 阶段保存 LastKey 即可完成去重。
小表大表Join(MapJoin)。
开启 Map 端聚合参数设置,防止数据倾斜。
一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替换。
尽量避免笛卡尔积。
合理设置 Map 及 Reduce 数。
小文件进行合并。
严格模式:where 语句中含有分区字段过滤条件来限制范围,否则不允许执行。
JVM 重用。
压缩。
mapJoin 适用于大表 join 小表,使用 DistributedCache 机制将小表存储到各个 Mapper 进程所在机器的磁盘空间上,各个 Mapper 进程读取不同的大表分片,将分片中的每一条记录与小表中所有记录进行合并。
合并后直接输出 map 结果即可得到最终结果。不需要进行 shuffle 流程,也不需要 reduce 处理。
框架选型:Apache、CDH、云服务器,各组件的兼容性。
服务器选型:数据量、预算、多久不扩容,算出需要对 CPU、内存、磁盘,集群规模。
节点功能规划:哪些机器部署哪些框架。
常用命令
命令 | 命令解释 |
---|---|
top | 查看内存 |
df -h | 查看磁盘存储情况 |
iotop | 查看磁盘IO读写 |
iotop -o | 直接查看比较高的磁盘读写程序 |
netstat -tunlp | grep 端口号 | 查看端口占用情况 |
uptime | 查看报告系统运行时长及平均负载 |
ps -ef | 查看进程 |
linux 查看 cpu 信息的方法:使用 “cat /proc/cpuinfo” 命令。
上面的 6、7、8 都是这一问的铺垫。问题都是循序渐进的。
思路:定位 Java服务进程 → 定位 Java 线程 → 定位代码块。
top
命令可查看是哪个服务 cpu 使用率较高。ps
来分析进程和线程的占用情况。jstack
来进行虚拟机栈的区分。通过 16 进制的 TID 查找问题所在的代码块。该题是下面三个题的铺垫。