Hive的数据抽样

March 12, 2019
作者:星爷
出处:http://lxWei.github.io/posts/Hive%E7%9A%84%E6%95%B0%E6%8D%AE%E6%8A%BD%E6%A0%B7.html
声明:转载请注明作者及出处。

最近在做Hive的数据抽样,基于以下考虑:

要求:

1. 抽样方案

1.1 方案一:Block Sampling

Hive 本身提供了抽样函数,使用TABLESAMPLE 抽取指定的 行数/比例/大小,举例:

CREATE TABLE XXX AS SELECT * FROM YYY TABLESAMPLE(1000 ROWS);
CREATE TABLE XXX AS SELECT * FROM YYY TABLESAMPLE (20 PERCENT); // 测试未生效
CREATE TABLE XXX AS SELECT * FROM YYY TABLESAMPLE(1M);          // 测试未生效

缺点:不随机。该方法实际上是按照文件中的顺序返回数据,对分区表,从头开始抽取,可能造成只有前面几个分区的数据。

优点:速度快。

1.2 方案二:分桶表抽样 (Smapling Bucketized Table)

利用分桶表,随机分到多个桶里,然后抽取指定的一个桶。举例:随机分到10个桶,抽取第一个桶。

CREATE TABLE XXX AS SELECT * FROM YYY TABLESAMPLE (BUCKET 1 OUT OF 10 ON rand());

优点:随机,测试发现,速度比方法3的rand()快。

1.3 方案三:随机抽样 rand

原理:利用rand()函数进行抽取,rand() 返回一个0到1之间的double 值。

法1

CREATE TABLE XXX AS 
SELECT * FROM YYY 
	ORDER BY rand() 
	limit 10000

此时,可以提供真正的随机抽样,但是,需要在单个reducer中进行总排序,速度慢

法2

CREATE TABLE XXX AS 
SELECT * FROM YYY 
	SORT BY rand() 
	limit 10000

Hive 提供了sort bysort by 提供了单个reducer 内的排序功能,但不保证整体有序,上面的语句是不保证随机性的。

法3

CREATE TABLE XXX AS 
SELECT * FROM YYY 
	where rand()<0.002 
	distribute by rand() 
	sort by rand() 
	limit 10000;

where 条件首先进行一次map 端的优化,减少reducer 需要处理的数据量,提高速度。distribute by 将数据随机分布,然后在每个reducer内进行随机排序,最终取10000条数据(如果数据量不足,可以提高where条件的rand过滤值)

缺点:速度慢

优点:随机

法4

CREATE TABLE XXX AS 
SELECT * FROM YYY 
	where rand()<0.002 
	cluster by rand() 
	limit 10000;

cluster by 的功能是 distribute bysort by的功能相结合,在上面的例子中,distribute by rand() sort by rand() 进行了两次随机,cluster by rand() 仅一次随机,那么,会影响最终的抽样结果吗?

2. 分区

但是,上面的方法,会丢失掉分区信息

所以,需要结合动态分区:

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
INSERT INTO TABLE XXX partition(thedate) SELECT * FROM YYY TABLESAMPLE (BUCKET 1 OUT OF 10 ON rand()); 

博客评论被墙,关注公众号交流。