1、Hive本地MR
如果在hive中运行的sql本身数据量很小,那么使用本地mr的效率要比分布式的快很多。但是hive本地MR对内存使用很敏感,查询的数据不能太大,否则本地内存是吃不消的。
So the query processor will launch this task in a child jvm, which has the same heap size as the Mapper's. Since the Local Task may run out of memory, the query processor will measure the memory usage of the local task very carefully. Once the memory usage of the Local Task is higher than a threshold number. This Local Task will abort itself and tells the user that this table is too large to hold in the memory. User can change this threshold byset hive.mapjoin.localtask.max.memory.usage = 0.999
查询处理器会在一个子的jvm里运作这个任务,jvm堆大小跟Mapper的堆大小一样。本地MR可能内存消耗殆尽,查询处理器用精确的计算本地MR的内存大小,一旦内存超过了设定的值,那么这个MR就会自动kill掉。可以通过设置hive.mapjoin.localtask.max.memory.usage =0.9,这个值太保守。
set hive.exec.mode.local.auto=true; //开启本地mr
//设置local mr的最大输入数据量,当输入数据量小于这个值的时候会采用local mr的方式
set hive.exec.mode.local.auto.inputbytes.max=50000000;
//设置local mr的最大输入文件个数,当输入文件个数小于这个值的时候会采用local mr的方式
set hive.exec.mode.local.auto.tasks.max=10;
当这三个参数同时成立时候,才会采用本地mr
2、Mapjoin使用
就是把小的表加入内存,可以配置以下参数,是hive自动根据sql,选择使用common join或者map join
set hive.auto.convert.join = true;
hive.mapjoin.smalltable.filesize 默认值是25mb
link:http://blog.youkuaiyun.com/xqy1522/article/details/6699740
MapJoin
今天遇到一个hive的问题,如下hive sql:
select f.a,f.b from A t join B f on ( f.a=t.a and f.ftime=20110802)
该语句中B表有30亿行记录,A表只有100行记录,而且B表中数据倾斜特别严重,有一个key上有15亿行记录,在运行过程中特别的慢,而且在reduece的过程中遇有内存不够而报错。
为了解决用户的这个问题,考虑使用mapjoin,mapjoin的原理:
MAPJION会把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join操作,省去了reduce运行的效率也会高很多
这样就不会由于数据倾斜导致某个reduce上落数据太多而失败。于是原来的sql可以通过使用hint的方式指定join时使用mapjoin。
select /*+ mapjoin(A)*/ f.a,f.b from A t join B f on ( f.a=t.a and f.ftime=20110802)
再运行发现执行的效率比以前的写法高了好多。
mapjoin还有一个很大的好处是能够进行不等连接的join操作,如果将不等条件写在where中,那么mapreduce过程中会进行笛卡尔积,运行效率特别低,如果使用mapjoin操作,在map的过程中就完成了不等值的join操作,效率会高很多。
例子:
select A.a ,A.b from A join B where A.a>B.a
简单总结一下,mapjoin的使用场景:
1. 关联操作中有一张表非常小
2.不等值的链接操作
参考自:https://cwiki.apache.org/confluence/display/Hive/MapJoinOptimization
refer to :http://blog.youkuaiyun.com/liuxianbing119/article/details/8668635
MapJoin,顾名思义,会在Map端完成Join操作。这需要将Join操作的一个或多个表完全读入内存。
MapJoin的用法是在查询/子查询的SELECT关键字后面添加/*+ MAPJOIN(tablelist) */提示优化器转化为MapJoin(目前Hive的优化器不能自动优化MapJoin)。其中tablelist可以是一个表,或以逗号连接的表的列表。tablelist中的表将会读入内存,应该将小表写在这里。
PS:有用户说MapJoin在子查询中可能出现未知BUG。在大表和小表做笛卡尔积时,规避笛卡尔积的方法是,给Join添加一个Join key,原理很简单:将小表扩充一列join key,并将小表的条目复制数倍,join key各不相同;将大表扩充一列join key为随机数。