复习:聊聊hive随机采样①

Posted 浪尖聊大数据

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了复习:聊聊hive随机采样①相关的知识,希望对你有一定的参考价值。

数据量大的时候,对数据进行采样,然后再做模型分析。作为数据仓库的必备品hive,我们如何对其进行采样呢?

当然,浪尖写本文还有另一个目的就是复习hive的四by。不知是否有印象呢?


欢迎点击阅读原文,加入浪尖知识星球。


假设有一张包含100亿行的Hive表,希望有效地随机抽样一个固定行数的数据 - 比如10000。最明显(而且显然是错误的)的方法是:

select * from my_table
limit 10000;

如果不对表进行排序,Hive不保证数据的顺序,但在实践中,它们按照它们在文件中的顺序返回,所以这远非真正随机。那么接着可以尝试:

select * from my_table
order by rand()
limit 10000;

这确实提供了真正的随机数据,但性能并不是那么好。为了实现总排序,Hive必须将所有数据强制传输到单个reducer。该reducer将对整个数据集进行排序。这很不好。幸运的是,Hive有一个非标准SQL“sort by”子句,它只在单个reducer中排序,并且不保证数据跨多个reducers中排序:

select * from my_table
sort by rand()
limit 10000;

这要好得多,但我不相信它真的是随机的。问题是Hive的将数据拆分为多个reducer的方法是未定义的。它可能是真正随机的,它可能基于文件顺序,它可能基于数据中的某些值。Hive如何在reducers中实现limit子句也是未定义的。也许它按顺序从reducer中获取数据 - 即,reducer 0中的所有数据,然后全部来reducer1,等等。也许它通过它们循环并将所有内容混合在一起。

在最坏的情况下,假设reduce 的key是基于数据列,而limit子句是reducers的顺序。然后样品会非常倾斜。

解决方案是另一个非标准的Hive功能:“distribute by”。对于reduce key不是由查询结构确定的查询(没有“group by”,没有join),可以准确指定reduce key的内容。如果我们随机分布,并在每个reducer中随机排序,那么“limit”功能如何无关紧要。

select * from my_table
distribute by rand()
sort by rand()
limit 10000;

最后,作为最后一次优化,可以在map-side做一些过滤。如果表的总大小是已知的,轻松设置一个随机阈值条件来进行数据过滤,如下所示:

select * from my_table
where rand() <= 0.0001
distribute by rand()
sort by rand()
limit 10000;

在这种情况下,由于总大小是100亿,样本大小是一万,我可以很容易地计算出样本占总数据的0.000001。但是,如果where子句是“rand()<0.000001”,则最终输出的行数可能少于10000行。“rand()<0.000002”可能会起作用,但这确实依赖于rand()有非常好的实现。最后它并不重要,因为瓶颈是全表扫描,而不是传输给reducer的这点数据。

推荐阅读:




以上是关于复习:聊聊hive随机采样①的主要内容,如果未能解决你的问题,请参考以下文章

随机过采样与随机欠采样 代码

随机过采样与随机欠采样 代码

PCL:RandomSample ❤️ 随机下采样

更改 randomForest R 代码中节点特征子集选择的采样方法

根据 HIVE 表中的时间戳确定每个唯一值的采样间隔

OpenGL均匀采样器2D具有相同的图像