当前位置:首页 > 开发 > 系统架构 > 架构 > 正文

hadoop 排序优化

发表于: 2014-04-08   作者:blackproof   来源:转载   浏览次数:
摘要: 转:http://blog.csdn.net/wf1982/article/details/7369324   hive 全排序优化 全排序 Hive的排序关键字是SORT BY,它有意区别于传统数据库的ORDER BY也是为了强调两者的区别–SORT BY只能在单机范围内排序。考虑以下表定义: CREATE TABLE if not exists t_order( id in

转:http://blog.csdn.net/wf1982/article/details/7369324

 

hive 全排序优化

全排序

Hive的排序关键字是SORT BY,它有意区别于传统数据库的ORDER BY也是为了强调两者的区别–SORT BY只能在单机范围内排序。考虑以下表定义:

CREATE TABLE if not exists t_order( id int, -- 订单编号 sale_id int, -- 销售ID customer_id int, --客户ID product _id int, -- 产品ID amount int -- 数量 ) PARTITIONED BY (ds STRING);

在表中查询所有销售记录,并按照销售ID和数量排序:

set mapred.reduce.tasks=2; Select sale_id, amount from t_order Sort by sale_id, amount;

这一查询可能得到非期望的排序。指定的2reducer分发到的数据可能是(各自排序):

Reducer1

Sale_id | amount 0 | 100 1 | 30 1 | 50 2 | 20

Reducer2

Sale_id | amount 0 | 110 0 | 120 3 | 50 4 | 20

因为上述查询没有reduce keyhive会生成随机数作为reduce key。这样的话输入记录也随机地被分发到不同reducer机器上去了。为了保证reducer之间没有重复的sale_id记录,可以使用DISTRIBUTE BY关键字指定分发keysale_id。改造后的HQL如下:

set mapred.reduce.tasks=2; Select sale_id, amount from t_order Distribute by sale_id Sort by sale_id, amount;

这样能够保证查询的销售记录集合中,销售ID对应的数量是正确排序的,但是销售ID不能正确排序,原因是hive使用hadoop默认的HashPartitioner分发数据。

这就涉及到一个全排序的问题。解决的办法无外乎两种:

1.) 不分发数据,使用单个reducer

set mapred.reduce.tasks=1;

这一方法的缺陷在于reduce端成为了性能瓶颈,而且在数据量大的情况下一般都无法得到结果。但是实践中这仍然是最常用的方法,原因是通常排序的查询是为了得到排名靠前的若干结果,因此可以用limit子句大大减少数据量。使用limit n后,传输到reduce端(单机)的数据记录数就减少到n* map个数)。

2.) 修改Partitioner,这种方法可以做到全排序。这里可以使用Hadoop自带的TotalOrderPartitioner(来自于Yahoo!TeraSort项目),这是一个为了支持跨reducer分发有序数据开发的Partitioner,它需要一个SequenceFile格式的文件指定分发的数据区间。如果我们已经生成了这一文件(存储在/tmp/range_key_list,分成100reducer),可以将上述查询改写为

set mapred.reduce.tasks=100; set hive.mapred.partitioner=org.apache.hadoop.mapred.lib.TotalOrderPartitioner; set total.order.partitioner.path=/tmp/ range_key_list; Select sale_id, amount from t_order Cluster by sale_id Sort by amount;

有很多种方法生成这一区间文件(例如hadoop自带的o.a.h.mapreduce.lib.partition.InputSampler工具)。这里介绍用Hive生成的方法,例如有一个按id有序的t_sale表:

CREATE TABLE if not exists t_sale ( id int, name string, loc string );

则生成按sale_id分发的区间文件的方法是:

create external table range_keys(sale_id int) row format serde'org.apache.hadoop.hive.serde2.binarysortable.BinarySortableSerDe' stored as inputformat'org.apache.hadoop.mapred.TextInputFormat' outputformat'org.apache.hadoop.hive.ql.io.HiveNullValueSequenceFileOutputFormat' location '/tmp/range_key_list';  insert overwrite table range_keys select distinct sale_id from source t_sale sampletable(BUCKET 100 OUT OF 100 ON rand()) s sort by sale_id;

生成的文件(/tmp/range_key_list目录下)可以让TotalOrderPartitionersale_id有序地分发reduce处理的数据。区间文件需要考虑的主要问题是数据分发的均衡性,这有赖于对数据深入的理解。

 

测试案例:

数据 140g, 按照字段time 降序排列 选出最大的前50个。

 

使用 一般方法 select * from table order by time desc limit 50.  执行了1小时6分钟完全算出。

任务数1个  map数  1783 reduce 1

而 select * from (select * from table distribute by time sort by time desc limit 50 ) t order by time desc limit 50;

需要5分钟算出。结果一致。

任务数2个   分别是:

map  1783 reduce 245

map 245 reduce   1

hadoop 排序优化

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
6.4.3 优化洗牌(shuffle)和排序阶段 洗牌和排序阶段都很耗费资源。洗牌需要在map和reduce任务之间
下面是排序代码: package gruopcount; import java.io.IOException; import java.net.URI; import
前言 Hadoop二次排序简单说就是先根据字段A分组排序,然后在对组内根据字段B排序。Hadoop二次排序在
前言 Hadoop二次排序在面试的时候出现频率还是比较高的。今天花了点时间通过源码深入学习了一下。后
在 Partitioner组件的设计与实现中,我们已经了解过Partitioner组件的其中一个和全排序相关的实现类
4.2 排序(SORT) 在MapReduce中,排序的目的有两个: MapReduce可以通过排序将Map输出的键分组。然
4.2.2 总排序(Total order sorting) 有的时候需要将作业的的所有输出进行总排序,使各个输出之间
一. 快速排序的基本思想 快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分
http://www.cnblogs.com/vivounicorn/archive/2011/09/20/2182433.html 之前在实现一些机器学习算法
题目1 : 拓扑排序·二 时间限制: 10000ms 单点时限: 1000ms 内存限制: 256MB 描述 小Hi和小Ho所在学
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号