蜂巢地图加入。 Hive 选择更大的表存储在缓存中
Posted
技术标签:
【中文标题】蜂巢地图加入。 Hive 选择更大的表存储在缓存中【英文标题】:Hive Map Join. Hive picking the bigger table to store in cache 【发布时间】:2016-10-24 17:34:33 【问题描述】:我设置了以下属性。
set hive.auto.convert.join=true;
set hive.optimize.ppd=true;
表 A 有 2500 万条记录。表 B 有 4400 万条记录。但是 where 子句存在条件,它在表 B 上具有过滤器。因此,在应用过滤器后,记录数下降到 200 万。
HIVE 选择表 A,而不是处理表 B 的映射连接。2500 万条记录缓存到所有数据节点中。
下面是使用的查询
select col1,col2,col3,col4
from table_A a
join
table_B c
on
a.account_number=c.account_number and c.ins_date between '$date_6' and '$date_cur'.
应该怎么做才能确保 HIVE 缓存表 B?
在更大的表上包含流表提示后进行计划-
阶段依赖性: 第 4 阶段是根阶段 Stage-3 取决于阶段: Stage-4 阶段 0 取决于阶段:阶段 3 舞台计划: 阶段:第四阶段 地图减少本地工作 别名 -> 映射本地表: b 获取运算符 限制:-1 别名 -> 映射局部运算符树: b 表扫描 别名:b 统计:行数:23894045 数据大小:7048743275 基本统计:COMPLETE 列统计:无 哈希表接收器运算符 条件表达式: 0 cm_mac_fin wan_mac 重启 重启 day_id 1 部门 地区 键: 0 cm_mac_fin(类型:字符串) 1个mac(类型:字符串) 阶段:阶段 3 地图缩减 地图运算符树: 表扫描 别名:一 统计:行数:2599797 数据大小:678547017 基本统计:COMPLETE 列统计:无 映射连接运算符 条件图: 左外连接0到1 条件表达式: 0 cm_mac_fin wan_mac 重启 重启 day_id 1 mac division region 键: 0 cm_mac_fin(类型:字符串) 1个mac(类型:字符串) 输出列名:_col0、_col1、_col2、_col3、_col4、_col8、_col9、_col10 统计信息:行数:26283450 数据大小:7753617770 基本统计信息:COMPLETE 列统计信息:NONE 选择运算符 表达式:_col0(类型:字符串)、_col1(类型:字符串)、_col2(类型:int)、_col3(类型:int)、_col4(类型:日期)、_col8(类型:字符串)、_col9(类型:字符串) , _col10(类型:字符串) 输出列名:_col0、_col1、_col2、_col3、_col4、_col5、_col6、_col7 统计信息:行数:26283450 数据大小:7753617770 基本统计信息:COMPLETE 列统计信息:NONE 文件输出运算符 压缩:假 统计信息:行数:26283450 数据大小:7753617770 基本统计信息:COMPLETE 列统计信息:NONE 桌子: 输入格式:org.apache.hadoop.mapred.TextInputFormat 输出格式:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat serde:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe 本地工作: 地图减少本地工作 执行方式:矢量化 阶段:Stage-0 获取运算符 限制:-1 处理器树: 列表接收器
在较小的表上包含地图连接提示后进行计划-
阶段依赖性: 第 4 阶段是根阶段 Stage-3 取决于阶段: Stage-4 阶段 0 取决于阶段:阶段 3 舞台计划: 阶段:第四阶段 地图减少本地工作 别名 -> 映射本地表: b 获取运算符 限制:-1 别名 -> 映射局部运算符树: b 表扫描 别名:b 统计:行数:23894045 数据大小:7048743275 基本统计:COMPLETE 列统计:无 哈希表接收器运算符 条件表达式: 0 cm_mac_fin wan_mac 重启 重启 day_id 1 部门 地区 键: 0 cm_mac_fin(类型:字符串) 1个mac(类型:字符串) 阶段:阶段 3 地图缩减 地图运算符树: 表扫描 别名:一 统计:行数:2599797 数据大小:678547017 基本统计:COMPLETE 列统计:无 映射连接运算符 条件图: 左外连接0到1 条件表达式: 0 cm_mac_fin wan_mac 重启 重启 day_id 1 mac division region 键: 0 cm_mac_fin(类型:字符串) 1个mac(类型:字符串) 输出列名:_col0、_col1、_col2、_col3、_col4、_col8、_col9、_col10 统计信息:行数:26283450 数据大小:7753617770 基本统计信息:COMPLETE 列统计信息:NONE 选择运算符 表达式:_col0(类型:字符串)、_col1(类型:字符串)、_col2(类型:int)、_col3(类型:int)、_col4(类型:日期)、_col8(类型:字符串)、_col9(类型:字符串) , _col10(类型:字符串) 输出列名:_col0、_col1、_col2、_col3、_col4、_col5、_col6、_col7 统计信息:行数:26283450 数据大小:7753617770 基本统计信息:COMPLETE 列统计信息:NONE 文件输出运算符 压缩:假 统计信息:行数:26283450 数据大小:7753617770 基本统计信息:COMPLETE 列统计信息:NONE 桌子: 输入格式:org.apache.hadoop.mapred.TextInputFormat 输出格式:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat serde:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe 本地工作: 地图减少本地工作 执行方式:矢量化 阶段:Stage-0 获取运算符 限制:-1 处理器树: 列表接收器
【问题讨论】:
【参考方案1】:Hive 内部使用多个因素来确定缓存表和流表以进行连接:
它根据配置标志 (hive.auto.convert.join.noconditionaltask, hive.auto.convert.join.noconditionaltask.size, hive.mapjoin.smalltable.filesize
) 将查询转换为映射连接。
大小配置使用户能够控制内存中可以容纳的大小表。
假设 n 个表参与连接,则连接的 n-1 个表必须放入内存中才能使映射连接优化生效。
当 n=2 且参数 hive.auto.convert.join
设置为 true 时,hive 会进行 mapjoins 并缓存小于 hive.mapjoin.smalltable.filesize
此参数的表。
在您的情况下,您可以显式指定缓存表而不是配置单元来确定它:
select /*+MAPJOIN(c)*/ col1,col2,col3,col4
from table_A a
join
table_B c
on
a.account_number=c.account_number and c.ins_date between '$date_6' and '$date_cur'.
【讨论】:
嗨 Rahul- 如果我们执行左连接而不是内连接,提示会起作用吗?我需要缓存外部表。 是的,如果是左连接,您需要一个表中的所有记录,因此该表应该是流式的,而另一个连接表可以是缓存或内存中的。 select /*+MAPJOIN(a)*/ col1,col2,col3,col4 from table_A a left join table_B c on a.account_number=c.account_number and c.ins_date between '$date_6' and '$date_cur'。表 A 比表 B 小,因此我希望表 A 被缓存。我给出了提示,但配置单元仍然没有缓存表 A。它正在缓存表 B。知道为什么吗? 试试这个: select /*+ STREAMTABLE(c) */ col1,col2,col3,col4 from table_A a left join ( select * from table_B cins_date between 'pqr' and 'xyz') c on a.account_number=c.account_number。 还分享两个查询的解释命令响应。解释 select /*+MAPJOIN(a)*/ col1,col2,col3,col4 from table_A a left join table_B c on a.account_number=c.account_number和 '$date_6' 和 '$date_cur' 之间的 c.ins_date【参考方案2】:在加入前将 where 子句移至 CTE。
WITH b as (
SELECT col1,col2,col3,col4
FROM table_B
WHERE ins_date between '$date_6' and '$date_cur'
)
SELECT col1,col2,col3,col4
FROM table_A a join b
on a.account_number = b.account_number;
这样,连接右侧的 b 只有 200 万条记录,因此被加载到 RAM 中。
【讨论】:
以上是关于蜂巢地图加入。 Hive 选择更大的表存储在缓存中的主要内容,如果未能解决你的问题,请参考以下文章