多维分析底层数据模型设计

两种模型分析

cube聚合结果冗余模型

  • 查询事业部的数据:select bu_id, amount from table where dt=20211001 and bu_id>0 and cat1_id=-1 and cat2_id=-1;
dt bu_id cat1_id cat2_id amount
20211001 110100 1001 11001 100
20211001 110100 1001 11002 100
20211001 110100 1001 -1 200
20211001 110100 -1 -1 200
20211001 310300 1001 11001 300
20211001 310300 1001 -1 300
20211001 310300 -1 -1 300
20211001 -1 -1 -1 500

基于明细的实时聚合模型

  • 查询事业部的数据:select bu_id, sum(amount) as amount from table where dt=20211001 group by bu_id;
dt bu_id cat1_id cat2_id amount
20211001 110100 1001 11001 100
20211001 110100 1001 11002 100
20211001 310300 1001 11001 300
对比 细分对比 cube聚合结果冗余模型 基于明细的实时聚合模型
数据存储 数据条数 ❌ 数据条数多(结果冗余),维度组合越多,维度粒度越细,数据条数膨胀越厉害 ✅ 数据条数少,跟维度的粗细粒度有关系,维度越多越细,数据条数越多,但是膨胀不会太大
数据存储 单条数据大小 ✅ 字段类型都是数值类型,每条数据的空间占用都不大 ❌ 根据doris指标类型差异很大:数值类型的指标,空间占用不大bitmap类型的指标,如果hive表明细数据量非常大(例如流量数据),存储的bitmap会非常大
数据存储 总体数据量 数据量只跟条数有关系,也就是维度组合的多少&维度粒度粗细有关系(例子,商品多维分析,维度组合多且维度很细,所以存储的数据量非常大,导入出现过瓶颈) 基本上受单条数据的大小影响更大,也就是指标类型的影响更大,如果指标都是bitmap类型,且hive底表数据量很大,那么doris的存储会很大(例子,流量多维分析,虽然每天的条数不多,但是占用的存储非常大,数据导入非常困难)
数据存储 数据导入 ❌ 使用唯一模型,导入字段都是数值类型,导入速度跟数据条数有关 ❌ bitmap列越多越慢,主要体现在全局字典的构建和doris聚合数据的压力,以及bitmap的大小,目前平台的stream load和spark load两种方式对于bitmap的导入支持都不是很好
数据存储 数据计算 ✅ 不需要聚合模型,唯一模型即可,不需要计算 ❌ bitmap类型的指标多&hive表明细数据量非常大,会造成doris的聚合计算压力非常大,数据导入慢(例子,流量多维分析,bitmap非常大,数据导入load阶段压力非常大)
数据查询 数据查询性能 ✅ 查询性能很快,只需要select * ❌ 查询性能跟数据量和指标类型关系很大,时间范围选的越长,查询时间增大明显
数据查询 数据查询组件 起源不支持,可以使用自建的cube冗余模型查询组件 ✅ 直接使用起源的数据应用出数
数据查询 性能优化方案 ✅ 基本上不需要优化,过慢的查询可以适当创建rollup ❌ 必须要创建rollup,但是多维分析的维度组合太多,理论上需要创建的rollup非常多,但是需要考虑数据的导入性能,所以实际上rollup只能适当创建,性能优化比较困难
数据查询 查询复杂度 ❌ 需要补充查询条件的维度之外的维度为-1,且需要考虑维度之间的级联关系,复杂度相对较高 ✅ 只需要把查询条件和分组条件添加到sql中,其他的条件不需要关心
产品功能灵活性 鉴权 ❌ 不能支持鉴权,包括事业部鉴权和品类鉴权事业部鉴权勉强还可以支持,但是只能限制用户选一个事业部,不能看有权限的全部事业部的汇总数据 ✅ 可以支持
产品功能灵活性 自定义时间 ❌ 不能支持自定义时间的聚合,只能支持固定的日周月、汇报周等 ✅ 可以支持

流量多维分析案例

流量多维分析的数据导入和查询都出现了瓶颈

doris集群配置:

  • FE3台:32G+16核
  • BE5台:256G内存+64核 6T*12硬盘

doris表数据量:

  • 维度数量:9个
  • 指标数量:22个,bitmap指标21个
  • 一天的数据条数:73823
  • 表的总大小:1.864 TB(202010-202110,一年数据),副本数量3,bucket数量5

hive表数据量:

  • 一天的数据量:75631702

doris数据导入任务:

  • 一次导入4天的数据不会出错,导入时间范围超过4天,会出现load的时候异常

doris表数据查询:

  • 查询2个月的数据会出现查询超时的情况,1个月偶尔也会

1. 冗余cube聚合结果模型

1.1 冗余cube聚合结果与起源

  • 需要手动添加-1的条件:开发工作量较大,而且需要判断维度之间的层级关系,不如说用户查询某个具体的二级类目,没有指定一级类目,但是一级类目这个维度不能是-1
  • 需要添加所有维度为group by列:对于查询性能有一定影响,尤其是维度比较多的情况下,指标也需要强行添加聚合函数
  • 无法进行衍生计算:
    • 类似于品类销售额占比这个指标,会配置一个衍生模型,依赖两个指标作为分子和分母
    • 分母需要配置移除维度,也就是说,拼装sql的时候,起源会自动将用户提交的sql中的品类条件移除掉
    • 但是对于冗余cube模型,移除类目条件是不够的,需要添加类目=-1的条件,这一点起源是做不到的
    • 起源通过支持grouping set和cube两种模型,并且支持维度的默认值设置,以及维度级联关系的设置,很好的支持了冗余cube模型的查询

1.2 起源对于冗余cube模型的支持

冗余cube模型这种叫法不是很规范,后续建议以起源的叫法为准,起源将模型的聚合类型分为三种:

  • 普通:对模型包含的全部维度进行聚合查询
  • groupingsets:对不同的维度组进行聚合预计算
  • with cube:对维度组内任意的维度集合进行聚合预计算(仅支持创建一个维度组)

我们所说的冗余cube实际上对应的是grouping set和with cube这两种聚合类型,grouping set是with cube的子集。这两种数据聚合方式,是通过预计算的方式,将数据提前计算,各个维度组合的计算结果保存在一起,查询的时候不需要聚合,只需要简单的select。因为所有的聚合结果都存储在一起,所以被聚合的维度会给一个默认值,起源提供了维度粒度设置功能,可以给维度设置默认值。

同时,该功能会配合级联维度功能,级联的维度比如region/bu,如果bu设置了具体的值,即使用户没有设置region的值,也不会补充-1。

选择了冗余的这两种模型之后,指标计算方式的配置可以选择『无聚合方式』,此时产生的sql中不会有group by和sum等聚合函数。

2. 实时聚合的聚合模型

  • doris导入压力很大,因为全局字典和导入的bitmap指标聚合计算,需求迭代重刷数据非常困难
  • 聚合计算压力大,尤其是时间范围选的比较大,周月维度不能预聚合的场景