欢迎来到皮皮网网首页

【cry指标源码】【编译火狐源码】【mapreduce Shuffle源码】hive count源码

来源:dnf源码讲解 时间:2024-11-25 10:29:24

1.Presto中SUM/COUNT踩坑
2.小技巧一:把roaring bitmap引入hive/spark,再也不怕count(distinct)了
3.Hive常用算子实现原理简述--MapReduce版

hive count源码

Presto中SUM/COUNT踩坑

       åŽŸå› ï¼šåœ¨presto中:两个value相除,至少有一个为浮点数才能返回正确结果

        解决方案:转为浮点型

        (1)select sum(case when storecode = '' then 1 else 0 end)*1. / count(1) from orders;

        (2)cast(value AS type)

        select * from table where date=

        在hive中正常执行,presto中会报错:operator equal(varchar, bigint) are not registered

        原因:Presto不支持隐式转换,要求什么格式的参数,就一定得是什么格式的参数

        改为select * from table where date=‘’

        在kylin中跑sum()/count() 和在presto中跑相同的sum/count结果不一致,原因分析:发现在kylin中count字段是不忽略null值的,应该怎么解决kylin中的这个问题(KYLIN中没有avg函数,真是不够用)

        目前的方法有:

        重新构建一个cube(忽略null值的)

        更改avg的口径问题(不可取....)

        更改cube中null字段的数据类型

小技巧一:把roaring bitmap引入hive/spark,再也不怕count(distinct)了

       小技巧一:引入Roaring Bitmap到Hive/Spark,解决count(distinct)问题

       在SQL中,`count(distinct xxx)`常用于计算去重数量。当`xxx`为byte,cry指标源码 shortint, int等数值类型时,可以将其转化为bitmap位运算,加速运算。对于非数值类型,可以考虑将其转换为一个唯一的数字,构建广义字典。Roaring Bitmap的基本思想是使用一个位图来唯一标记某个正整数,用于记录无重复的整数数组。

       例如,数组[2,3,4,5]可以通过一个字节记录。通过依次设置数字n在第n+1个位置的位,可以表示数组。编译火狐源码对于数字范围0到n,需要`n/ +1`字节的存储空间。与数组存储相比,Roaring Bitmap的存储空间通常更小,约为数组的1/。

       Roaring Bitmap适用于无法直接存储的其他类型数字,通过转换为唯一数字进行存储。在处理如`[0,mapreduce Shuffle源码]`的场景中,使用Roaring Bitmap需要字节的空间,而数组存储只需要8字节,因此不划算。Roaring Bitmap在底层采用数组存储,以适应数字分散的场景。

       当处理如`[0,]`和`[,0]`的场景时,Roaring Bitmap可能无法区分数字顺序或正确识别重复值。在大数据领域,xen源码解析如活跃人数等去重指标的计算中,Roaring Bitmap可以加速计算过程,尤其是在离线执行引擎Hive/Spark中引入Roaring Bitmap来实现精准去重。

       考虑到Hive本身不支持Roaring Bitmap数据类型,可以将其序列化为`binary`类型使用。在函数体系方面,需要实现一系列的UDF和UDAF函数,如`bitmap_count`、weex源码下载`bitmap_and`、`bitmap_not`、`bitmap_union`、`bitmap_contains`、`range_bitmap`、`bitmap_to_array`、`array_to_bitmap`等,以支持bitmap的集合计数、交集、差集、并集和查询操作。

       在留存分析场景中,可以利用Roaring Bitmap构建活跃位图来加速计算,如连续N天登录问题。通过将用户活跃日期构建为位图,可以快速判断用户是否连续活跃。在用户画像和用户圈选场景中,Roaring Bitmap可以用于构建用户活跃画像,提高数据处理效率。在电商场景中,通过构建轻度汇总表并使用Roaring Bitmap存储去重人数,可以有效避免重复计算,提高数据聚合的准确性。

       对于大数值范围(如bigint),Roaring Bitmap也支持。考虑到实际应用中数值范围超过`2**`的情况较少,是否需要支持bigint取决于具体需求。在数据索引优化方面,可以考虑重新编码,使得连续分布,进一步提高查询性能。

Hive常用算子实现原理简述--MapReduce版

       Hive中的常用算子包括distinct、join、group by、order by、distribute by、sort by、count等,这些操作符在SQL中使用起来很方便,能快速达到我们想要的效果,但是这些算子在底层是怎么实现的呢?

        order by很容易想到执行原理,在一个reduce中将所有记录按值排序即可。因此order by在数据量大的情况下执行时间非常长,容易out of memory,非特殊业务需求一般不使用。distribute by也比较明显,根据hash值将distribute的值分发到不同的reduce。sort by是小号的order by,只负责将本reducer中的值排序,达到局部有序的效果。sort by和distribute by配合使用风味更佳,二者可以合并简写为cluster by。count则更加明晰,在combiner或reducer处按相同键累加值就能得到。

        比较复杂的是distinct、join、group by,本文重点讨论这三个算子在MapReduce引擎中的大致实现原理。班门弄斧,抛砖引玉。

        map阶段,将group by后的字段组合作为key,如果group by单字段那么key就一个。将group by之后要进行的聚合操作字段作为值,如要进行count,则value是1;如要sum另一个字段,则value就是该字段。

        shuffle阶段,按照key的不同分发到不同的reducer。注意此时可能因为key分布不均匀而出现数据倾斜的问题。

        reduce阶段,将相同key的值累加或作其他需要的聚合操作,得到结果。

        对group by的过程讲解的比较清楚的是这篇文章 /info-detail-.html 图文并茂,很生动。

        实例如下图,对应语句是 select rank, isonline, count(*) from city group by rank, isonline;

        如果group by出现数据倾斜,除去替换key为随机数、提前挑出大数量级key值等通用调优方法,适用于group by的特殊方法有以下几种:

        (1)set hive.map.aggr=true,即开启map端的combiner,减少传到reducer的数据量,同时需设置参数hive.groupby.mapaggr.checkinterval 规定在 map 端进行聚合操作的条目数目。

        (2)设置mapred.reduce.tasks为较大数量,降低每个reducer处理的数据量。

        (3)set hive.groupby.skewindata=true,该参数可自动进行负载均衡。生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group ByKey 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce中),最后完成最终的聚合操作。

        Hive中有两种join方式:map join和common join

        如果不显式指定map side join,或者没有达到触发自动map join的条件,那么会进行reduce端的join,即common join,这种join包含map、shuffle、reduce三个步骤。

        (1)Map阶段

        读取源表的数据,Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key。Map输出的value为join之后所关心的(select或者where中需要用到的)列;同时在value中还会包含表的Tag信息,用于标明此value对应哪个表。然后按照key进行排序。

        (2)Shuffle阶段

        根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中

        (3)Reduce阶段

        根据key的值完成join操作,期间通过Tag来识别不同表中的数据。

        以下面的SQL为例,可用下图所示过程大致表达其join原理。

        SELECT u.name, o.orderid FROM user u JOIN order o ON u.uid = o.uid;

        关联字段是uid,因此以uid为map阶段的输出key,value为选取的字段name和标记源表的tag。shuffle阶段将相同key的键值对发到一起,reduce阶段将不同源表、同一key值的记录拼接起来,可能存在一对多的情况。

        如果指定使用map join的方式,或者join的其中一张表小于某个体积(默认MB),则会使用map join来执行。具体小表有多小,由参数 hive.mapjoin.smalltable.filesize 来决定。

        Hive0.7之前,需要使用hint提示 /*+ mapjoin(table) */才会执行MapJoin,否则执行Common Join,但在0.7版本之后,默认自动会转换Map Join,由参数 hive.auto.convert.join 来控制,默认为true。

        以下图为例说明map join如何执行,该图来自 /archives///.htm ,博主是一个水平深厚又乐于分享的前辈,图片水印上也有其网址。

        yarn会启动一个Local Task(在客户端本地执行的Task)--Task A,负责扫描小表b的数据,将其转换成一个HashTable的数据结构,并写入本地的文件中,之后将该文件加载到DistributeCache中。

        接下来是Task B,该任务是一个没有Reduce的MR,启动MapTasks扫描大表a,在Map阶段,根据a的每一条记录去和DistributeCache中b表对应的HashTable关联,并直接输出结果。

        由于MapJoin没有Reduce,所以由Map直接输出结果文件,有多少个Map Task,就有多少个结果文件。

        distinct一般和group by同时出现。

        当distinct一个字段时,将group by的字段和distinct的字段组合在一起作为map输出的key,value设置为1,同时将group by的字段定为分区键,这可以确保相同group by字段的记录都分到同一个reducer,并且map的输入天然就是按照组合key排好序的。根据分区键将记录分发到reduce端后,按顺序取出组合键中的distinct字段,这时distinct字段也是排好序的。依次遍历distinct字段,每找到一个不同值,计数器就自增1,即可得到count distinct结果。例如下面的SQL语句,过程可以下图示意。

        我暂时没有理解这是怎么实现的,别人写的也没有看明白。有善良的学富五车的大佬指点一下吗?