hive 架构如图所示, client 跟 driver 交互, 通过 parser,planner,optimizer, 最后转为 mapreduce 运行, 具体步骤如下
driver 输入一条 sql, 会由 parser 转为抽象语法树 AST, 这个是没有任务元数据信息的语法树;
语法分析器再把 AST 转为一个一个的 QueryBlock, 一个 QueryBlock 包含输入, 输出, 计算逻辑, 也就是说一个子程序就是 QueryBlock
planner 遍历所有的 QueryBlock, 转为一个个的 Operator(算子, 比如 tablescanOperator), 最后形成 OperatorTree;
优化器对 OperatorTree 进行优化, 包含谓词下推, 剪枝等;
然后遍历 OperatorTree, 分割成多个 mapreduce 作业, 形成物理计划
之后进行物理优化, 比如是否进行 map join 等
Hive 数据倾斜优化
对于 group by 可以有两个优化点
map 聚合: set hive.map.aggr=true, 会在 map 端对相同 key 先聚合一下;
分发为两道作业: set hive.groupby.skewindata=true, 会对原来的一道作业分为两道作业, 第一道随机分配 key, 第二道再按 key 分配
注意: 对于部分聚合函数有用, 比如 sum 和 count, 但是完全聚合函数无用, 比如 avg
对于 join 也有两个优化点
map join: 新版 hive 中默认开启 set hive.auto.convert.join=true ,join 的左表如果足够小, 会直接把左表内容加载到内存中
两道作业: set hive.optimize.skewjoin = true;set hive.skewjoin.key = skew_key_threshold (default = 100000) 这个两道作业跟 groupby 不一样, 这个是说把超过 10 万行的数据单独启一道 map join, 最后再把结果聚合
hive 常见问题
hive 不支持非等值 join
错误: select from a inner join b on a.id<>b.id
替代方法: select from a inner join b on a.id=b.id and a.id is null;
hive 不支持非 join 连接
错误: select from dual a,dual b where a.key = b.key;
正确: select from dual a join dual b on a.key = b.key;
hive 不支持 or
错误: select from a inner join b on a.id=b.id or a.name=b.name
替代方法: select from a inner join b on a.id=b.id union all select * from a inner join b on a.name=b.name
hive 内部表和外部表的区别
创建表时: 创建内部表时, 会将数据移动到数据仓库指向的路径; 若创建外部表, 仅记录数据所在的路径, 不对数据的位置做任何改变.
删除表时: 在删除表的时候, 内部表的元数据和数据会被一起删除, 而外部表只删除元数据, 不删除数据. 这样外部表相对来说更加安全些, 数据组织也更加灵活, 方便共享源数据
sortby,orderby,distributeby
order by 会引发全局排序; 会导致所有的数据集中在一台 reducer 节点上, 然后进行排序, 这样很可能会超过单个节点的磁盘和内存存储能力导致任务失败.
distribute by + sort by 就是该替代方案, 被 distribute by 设定的字段为 KEY, 数据会被 HASH 分发到不同的 reducer 机器上, 然后 sort by 会对同一个 reducer 机器上的每组数据进行局部排序.
来源: http://www.bubuko.com/infodetail-3061851.html