赞
踩
https://blog.csdn.net/lihuazaizheli/article/details/107674269
理解map reduce 编程思想(分而治之)
大数据量下优势明显,读写HDFS次数多
mapreduce流程
maptask:
reducetask:
map数由分片决定,若要增加map数,可增大mapred.map.tasks
,若减少map数,可增大mapred.min.split.size
。减少map个数,在map执行前合并小文件,可set mapred.map.split.size
reduce数量由分区数决定,结果文件的数量也由此决定,且记录默认按key升序排列。reduce数量可通过mapred.reduce.tasks
设置。
<“a”,1>
和<“a”,1>
,如果合并,会得到<“a”,2>
,如果归并,会得到<“a”,<1,1>>
由于Join/GroupBy/OrderBy均需要在Reduce阶段完成
select u.name, o.orderid from order o join user u on o.uid = u.uid;
select rank, isonline, count(*) from city group by rank, isonline;
select dealid, count(distinct uid) num from order group by dealid;
当只有一个distinct字段时,如果不考虑Map阶段的Hash GroupBy,只需要将GroupBy字段和Distinct字段组合为map输出key,利用mapreduce的排序,同时将GroupBy字段作为reduce的key,在reduce阶段保存LastKey即可完成去重
如果有多个distinct字段呢,如下面的SQL
select dealid, count(distinct uid), count(distinct date) from order group by dealid;
可以对所有的distinct字段编号,每行数据生成n行数据,那么相同字段就会分别排序,这时只需要在reduce阶段记录LastKey即可去重。这种实现方式很好的利用了MapReduce的排序,节省了reduce阶段去重的内存消耗,但是缺点是增加了shuffle的数据量。需要注意的是,在生成reduce value时,除第一个distinct字段所在行需要保留value值,其余distinct数据行value字段均可为空
外排序采用分块的方法(分而治之),首先将数据分块,对块内数据按选择一种高效的内排序策略进行排序。然后采用归并排序的思想对于所有的块进行排序,得到所有数据的一个有序序列。
把磁盘上的1TB数据分割为40块(chunks),每份25GB。(注意,要留一些系统空间!)
顺序将每份25GB数据读入内存,使用quick sort算法排序。
把排序好的数据(也是25GB)存放回磁盘。
循环40次,现在,所有的40个块都已经各自排序了。(剩下的工作就是如何把它们合并排序!)
从40个块中分别读取25G/40=0.625G入内存(40 input buffers)。
执行40路合并,并将合并结果临时存储于2GB 基于内存的输出缓冲区中。当缓冲区写满2GB时,写入硬盘上最终文件,并清空输出缓冲区;当40个输入缓冲区中任何一个处理完毕时,写入该缓冲区所对应的块中的下一个0.625GB,直到全部处理完成。
https://tech.meituan.com/2014/02/12/hive-sql-to-mapreduce.html
map段部分聚合
阶段拆分-两阶段聚合 需要聚合的key前加一个随机数的前后缀,这样就均匀了,之后再按照原始的key聚合一次
生成的查询计划有两 个 MapReduce 任务。在第一个 MapReduce 中,map 的输出结果集合会随机分布到 reduce 中, 每个 reduce 做部分聚合操作,并输出结果。相同的 Group By Key 有可 能分发到不同的 reduce 中,从而达到负载均衡的目的;第二个 MapReduce 任务再根据预处 理的数据结果按照 Group By Key 分布到 reduce 中(这个过程可以保证相同的 Group By Key 分布到同一个 reduce 中),最后完成最终的聚合操作。
假设 key = 水果
select count(substr(a.key,1,2)) as key
from(
select concat(key,'_',cast(round(10*rand())+1 as string)) tmp
from table
group by tmp
)a
group by key
1.在查询的时候,过滤掉所有为NULL的数据,比如:
SELECT * FROM log a
JOIN bmw_users b ON a.user_id IS NOT NULL AND a.user_id = b.user_id
UNION ALL
SELECT *FROM log a WHERE a.user_id IS NULL;
2.查询出空值并给其赋上随机数,避免了key值为空(数据倾斜中常用的一种技巧)
SELECT *FROM log a
LEFT JOIN bmw_users b ON
CASE WHEN a.user_id IS NULL THEN concat(‘dp_hive’, rand()) ELSE a.user_id END = b.user_id;
select count(distinct a) from test ;
select count x.a
from (select a from test group by a ) x
select a, count(distinct b) as c from tbl group by a;
select a, count(*) as c from (select a, b from tbl group by a, b) group by a;
当需要把用户表和日志表关联起来时,再日志表中有很多没注册的用户表,可以分开处理
select *from
(select * from logs where user_id = 0)a
join
(select * from users where user_id = 0)b
on a.user_id = b.user_id
union all
select * from logs a join users b on a.user_id <> 0 and a.user_id = b.user_id;
一张表 s8_log,每个商品一条记录,要和商品表关联。**s8_log 中有字符串商品 id,也有数字的商品 id。**字符串商品 id 类型是 string 的,但商品中的数字 id 是 bigint 的。
问题的原因是把 s8_log 的商品 id 转成数字 id 做 Hash(数字的 Hash 值为其本身,相同的字符串的 Hash 也不同)来分配 Reducer,所以相同字符串 id 的 s8_log,都到一个 Reducer 上了。
-- 把数字类型转换成字符串类型
SELECT *
FROM s8_log a
LEFT JOIN r_auction_auctions b ON a.auction_id = CAST(b.auction_id AS string);
SELECT *
FROM effect a
JOIN (
SELECT auction_id AS auction_id
FROM auctions
UNION ALL
SELECT auction_string_id AS auction_id
FROM auctions
) b
ON a.auction_id = b.auction_id;
**结论:**这样子比分别过滤数字 id,字符串 id ,然后分别和商品表关联性能要好。这样写的好处:1个 MR 作业,商品表只读取一次,推广效果表只读取一次。把这个 sql 换成 MR 代码的话,map 的时候,把 a 表的记录打上标签 a ,商品表记录每读取一条,打上标签 t,变成两个<key,value> 对,<t,数字id,value>,<t,字符串id,value>。所以商品表的 HDFS(Hadoop Distributed File System) 读只会是一次。
问题:比如推广效果表要和商品表关联,效果表中的 auction_id 列既有 32 为字符串商 品 id,也有数字 id,和商品表关联得到商品的信息。 比分别过滤数字 id,字符串 id 然后分别和商品表关联性能要好。
SELECT * FROM effect a
JOIN
(SELECT auction_id AS auction_id FROM auctions
UNION All
SELECT auction_string_id AS auction_id FROM auctions) b
ON a.auction_id=b.auction_id;
场景:有一张user表,为卖家每天收到表,user_id,ds(日期)为key,属性有主营类目,指标有交易金额,交易笔数。每天要取前10天的总收入,总笔数,和最近一天的主营类目。
SELECT user_id, substr(MAX(CONCAT(ds, cat)), 9) AS main_cat, SUM(qty), SUM(amt) FROM users
WHERE ds BETWEEN 20120301 AND 20120329
GROUP BY user_id
cluster by: 对同一字段分桶并排序,不能和sort by连用;
distribute by + sort by: 分桶,保证同一字段值只存在一个结果文件当中,结合sort by 保证每个reduceTask结果有序;
sort by: 单机排序,单个reduce结果有序
order by:全局排序,缺陷是只能使用一个reduce
今天也是爱zz的一天哦!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。