ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

02数仓开发-04数仓多维模型构建

2022-07-06 12:01:13  阅读:182  来源: 互联网

标签:02 数仓 good 10000 04 country xian 维度 1000


目录

一.背景

数仓建设中经常会有多个维度灵活组合看数的需求,这种多维分析的场景一般有两种处理方式

  • 即时查询

    • 适合计算引擎很强,查询灵活,并发量不大的场景
    • 数据链路:明细数据hive表-> MPP计算引擎
  • 预计算

    • 适合有固定模式的聚合查询。预计算的结果可以被不同下游复用
    • 数据链路: 明细数据-> 离线计算引擎 -> 多维cube结果hive表 -> MPP计算引擎(presto)

二.维度爆炸&下游易用

“维度爆炸”指的是每增加一个维度,由于维度组合数翻倍,Cube的计算和存储量也会成倍增长。

作为典型的预计算MOLAP框架,kylin如何解决维度爆炸问题的呢

  • 使用Partial Cube:通过聚合组进行剪枝,减少不必要的预计算组合
  • 设置衍生维度:将能通过其他维度计算出来的维度(例如id/name)设置为衍生维度,减少不必要的预计算;

类似的,在Spark中可以对所有维度组合都进行预计算( with cube 子句),

或者出于业务或者计算存储成本考虑只对一部分维度组合进行预计算(grouping sets 子句)。

grouping sets 方式剪枝后一定程度上可以避免维度爆炸,但还有以下痛点:

  • 各方沟通成本高: brd、prd、技术方案、代码各自维护一套维度组合

    • 需要大量时间和业务沟通、以确认维度组合
    • 只能拿到无意义的groupingid, 在数据产品使用时,看不清目前具体有哪些维度组合,用户筛选不直观问题
  • 维护成本高:SQL维护成本高,可能遗漏、重复

三.如何优化

示例:求各个维度组合的人数

维度组合: countrycityxianzhenis_good

  • 统一使用-10000表示“全部”,不处理“全部“、”全国”等中文
    select '中国' country , '北京' city , '昌平' xian ,'西北旺' zhen,1 is_good , 1000 p_num

1.grouping sets字句

8种维度组合

select
    nvl(country,-1000)  as country
    ,nvl(is_good,-1000) as is_good
    ,nvl(xian,-1000)    as xian
    ,nvl(city,-1000)    as city
    ,nvl(zhen,-1000)    as zhen
    ,sum(p_num)
from
(
    select '中国' country , '北京' city , '昌平' xian ,'西北旺' zhen,1 is_good , 1000 p_num
    -- union all
    -- select '中国' country , '河南' city , '光山' xian ,'十里' zhen,1 is_good , 50 p_num
) t 
group by country,city,xian,zhen,is_good
grouping sets (
    (country)
    ,(country,city)
    ,(country,xian)
    ,(country,xian,zhen)
    ,(country,is_good)
    ,(country,city,is_good)
    ,(country,xian,is_good)
    ,(country,xian,zhen,is_good)
)

运行结果:8条

country is_good xian city zhen _c5
中国 1 昌平 -1000 -1000 1000
中国 -1000 -1000 -1000 -1000 1000
中国 1 -1000 -1000 -1000 1000
中国 1 昌平 -1000 西北旺 1000
中国 -1000 -1000 北京 -1000 1000
中国 -1000 昌平 -1000 -1000 1000
中国 1 -1000 北京 -1000 1000
中国 -1000 昌平 -1000 西北旺 1000

2.lateral view + 自定义维度list

:8种维度组合

通过lateral view 维度list 对数据做笛卡尔积,每条数据膨胀成8条维度组合不同的数据。

select
    dims
    ,country
    ,is_good
    ,xian
    ,city
    ,zhen
    ,sum(p_num)
from
(
    select
        dims
        ,country --必选维度
        ,is_good
        ,if(find_in_set('县城', dims) > 0, xian, -10000) as xian
        ,if(find_in_set('城市', dims) > 0, city, -10000) as city
        ,if(find_in_set('城镇', dims) > 0, zhen, -10000) as zhen
        ,p_num
    from
    (   select
            array(is_good,-1000) as is_good_list
            ,country
            ,city
            ,xian
            ,zhen
            ,p_num
        from
        (
            select  '中国' country , '北京' city , '昌平' xian ,'西北旺' zhen,1 is_good , 1000 p_num
            -- union all
            -- select '中国' country , '河南' city , '光山' xian ,'十里' zhen,1 is_good , 50 p_num
        )t1
    )t2
    lateral view  explode(is_good_list) t1 as is_good
    lateral view  explode(array( '国家'
                                ,'国家,县城'
                                ,'国家,城市'
                                ,'国家,城市,城镇'
    )) t2 as dims
) tmp
group by dims,country,is_good,xian,city,zhen

运行结果:8条

dims country is_good xian city zhen SUM(p_num)
国家 中国 1 -10000 -10000 -10000 1000
国家 中国 -1000 -10000 -10000 -10000 1000
国家_县城 中国 1 昌平 -10000 -10000 1000
国家_县城 中国 -1000 昌平 -10000 -10000 1000
国家_城市 中国 1 -10000 北京 -10000 1000
国家_城市 中国 -1000 -10000 北京 -10000 1000
国家城市城镇 中国 1 -10000 北京 西北旺 1000
国家城市城镇 中国 -1000 -10000 北京 西北旺 1000

3.通过配置文件,维护维度list

配置表:conf_table

select
    `version`
    ,dim1
    ,dim2
    ,dim3
    ,dim4
    ,dt
from (
    select 'v1' as `version`,'国家' as dim1,'' as dim2 , '' dim3, '' dim4, '2022-07-05' as dt
    union all
    select 'v1' as `version`,'国家' as dim1,'县城' as dim2 , '' dim3, '' dim4, '2022-07-05' as dt
    union all
    select 'v1' as `version`,'国家' as dim1,'城市' as dim2 , '' dim3, '' dim4, '2022-07-05' as dt
    union all
    select 'v1' as `version`,'国家' as dim1,'城市' as dim2 , '城镇' dim3, '' dim4, '2022-07-05' as dt
) conf_table 

sql

select
    dims
    ,country
    ,is_good
    ,xian
    ,city
    ,zhen
    ,sum(p_num)
from
(
    select
        dims
        ,country --必选维度
        ,is_good
        ,if(find_in_set('县城', dims) > 0, xian, -10000) as xian
        ,if(find_in_set('城市', dims) > 0, city, -10000) as city
        ,if(find_in_set('城镇', dims) > 0, zhen, -10000) as zhen
        ,p_num
    from
    (   select
            array(is_good,-1000) as is_good_list
            ,country
            ,city
            ,xian
            ,zhen
            ,p_num
        from
        (
            select  '中国' country , '北京' city , '昌平' xian ,'西北旺' zhen,1 is_good , 1000 p_num
        )t1
    )t2
  	--配置表
    left join (
                select
                    concat_ws(',', array(dim1, dim2, dim3, dim4)) as dims
                from (
                    select 'v1' as `version`,'国家' as dim1,'' as dim2 , '' dim3, '' dim4, '2022-07-05' as dt
                    union all
                    select 'v1' as `version`,'国家' as dim1,'县城' as dim2 , '' dim3, '' dim4, '2022-07-05' as dt
                    union all
                    select 'v1' as `version`,'国家' as dim1,'城市' as dim2 , '' dim3, '' dim4, '2022-07-05' as dt
                    union all
                    select 'v1' as `version`,'国家' as dim1,'城市' as dim2 , '城镇' dim3, '' dim4, '2022-07-05' as dt
                ) conf_table
                where version = 'v1' and dt = '2022-07-05'
    ) conf_table
    on 1 = 1 --笛卡尔积
    lateral view  explode(is_good_list) tmp as is_good
) tmp
group by dims,country,is_good,xian,city,zhen
;
dims country is_good xian city zhen sum(p_num)
国家,县城,, 中国 -1000 昌平 -10000 -10000 1000
国家,县城,, 中国 1 昌平 -10000 -10000 1000
国家,城市,城镇, 中国 -1000 -10000 北京 西北旺 1000
国家,城市,, 中国 1 -10000 北京 -10000 1000
国家,,, 中国 -1000 -10000 -10000 -10000 1000
国家,城市,, 中国 -1000 -10000 北京 -10000 1000
国家,,, 中国 1 -10000 -10000 -10000 1000
国家,城市,城镇, 中国 1 -10000 北京 西北旺 1000

标签:02,数仓,good,10000,04,country,xian,维度,1000
来源: https://www.cnblogs.com/wh984763176/p/16450257.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有