最近在做一个项目时遇到一个问题,是关于大数据量的数据,具体为一个800亿的轻度汇总数据,去关联一个7亿左右的另一个轻度汇总数据。
主要遇到的问题有:
1,800亿的轻度汇总数据读写困难,耗费时间、资源大;
2,两表进行关联处理数据计算慢。
背景:(完全假设来说)
A表是以用户、城市维度的出现次数数据,字段主要有uid、city_id,cnt
B表是以用户、城市维度的出现次数标准数据,字段主要有uid、city_id,city_cnt
主要是求用户是否在某个省份达到出现次数标准的进度,比如说小明在济南出现2次,在青岛出现5次,
但是在济南出现的标准次数应该为4次,在青岛出现的标准次数为4次。所以在山东出现的标准次数为8次,而小明达标的次数分别为2次和4次(超过标准按照标准统计),所以小明在山东出现的次数进度为67%。
针对以上数据量,目前想到的方案有以下三种:
方案一:拆分数据、分散资源,建立多个计算task
(1)由于目的是对用户进行统计,所以对A、B表以及目标表根据uid首位数字设置分区,将数据量拆分;
首先需要对uid首位数进行数据量查询,然后按照数据量的大小进行合理分配分区。
(2)根据分区建多个task,跑入对应目标表的分区;
对相同分区下的用户数据进行数据计算,然后建立多个task进行跑数,分散资源。
方案二:维度进行高粒度汇总,减小数据量
(1)维护一张城市和省份的维度表,在A表的计算过程中进行聚合,直接输出用户到省份维度,省略用户对城市的维度(A表)。
这样的话,就获取不到A表,得不到用户对城市维度的明细数据,对与数仓建设和后期数据维护不友好,但是对于本次项目的统计确实性能得到很好的提升。如果效果不好的话可以再重复方案一在用户对省份维度上建立分区。
(2)再与其用户到省份维度的表进行关联。
方案三:维度直接汇总到最高用户维度,建立数组存储省份信息,最大粒度减小数据量。
(1)涉及到的底层表聚合到用户维度,其余对应的城市和次数字段做成数组进行存储。
建立以uid作为主键,其余字段作为数据map的表,最大限度的满足当前需求,但是不利于数仓基础表的维护,再做新需求利用到同样数据源还需要进行同样的操作
(2)解析数组,再进行关联,输入到目标表。
对所有汇总到用户维度的底层表进行解析数组,然后进行关联再计算。
针对以上方案,如果既需要满足本需求,又有利于数仓建设的话,推荐方案一,如果是敏捷开发,满足此需求的话推荐方案三,对于数据集市建设,如果没必要细致到用户到城市维度的话,建议方案二,三种方案各有利弊,具体选择需要根据实际情况定夺。
如果大家有更完美的方案的话,欢迎留言!
插曲:对于如何分区的话,可以参考一下本福特定律,但是对于有规则化的uid,没啥意义。
网友评论