最新域名解析网站网站设计网页设计
web/
2025/10/6 3:31:11/
文章来源:
最新域名解析网站,网站设计网页设计,网址搭建wordpress,长春网络公司做网站前言 今天开始 DIM 层的开发#xff0c;说开发好像有点不配#xff0c;还只是学习阶段#xff0c;离开发还有很长的路要走。 一个人想象自己不懂得的事很容易浪漫。 --《沉默的大多数》王小波 1、DIM 层开发
DIM层设计要点#xff1a;
DI…前言 今天开始 DIM 层的开发说开发好像有点不配还只是学习阶段离开发还有很长的路要走。 一个人想象自己不懂得的事很容易浪漫。 --《沉默的大多数》王小波 1、DIM 层开发
DIM层设计要点
DIM层的设计依据是维度建模理论该层存储维度模型的维度表。DIM层的数据存储格式为orc列式存储snappy压缩。DIM层表名的命名规范为dim_表名_全量表或者拉链表标识full/zip 我们在前面 ODS 层的开发时数据压缩用的是 gz 为的是最大的压缩存储。但是这里我们的 DIM 、DWD、DWS 层是之后用的最频繁的三层所以我们必须保证它的读取和解压缩更快所以我们选用 orc snappy 压缩。 维度表我们大致可以分为两类每日全量快照表和拉链表
DIM 层就是创建维度表的过程所以我们需要先回顾一下维度建模的知识
1.1、维度建模回顾 前面我们学习数据仓库构建流程的时候说 DWD 和 DIM 层是业务驱动的因为我们的事实表存在 DWD 层取决于业务系统中业务过程而我们的维度表存在 DIM 层取决于业务系统中的环境它俩都和我们的指标没啥关系。 在设计维度模型之前我们需要构建业务总线矩阵矩阵的行是一个个业务过程具体说就是每行代表一个业务事实表矩阵的列是一个个的维度代表一个维度表行列的交点表示业务过程与维度存在关联关系。 按照事务型事实表的设计流程我们就可以得到业务总线矩阵因为我们的维度模型是以事实表为核心而事实表主要就是事务型事实表。 这里只对红色框起来的部分维度进行建表而蓝色框的维度我们会做一个维度退化。回顾一下维度退化的定义 如果某些维度表的维度属性很少比如支付方式表没有必要去单独创建一个维度表因为它就一个支付方式字段则可不创建该维度表而把该表的维度属性直接增加到与之相关的事实表中这个操作称为维度退化。 也就是说我们直接把支付方式这个维度属性作为一个字段加到支付成功和退款成功这两个事实表当中把退单类型作为一个字段做到退款成功这个事实表当中... 还有渠道、设备这两个维度属性也要做维度退化尽管它俩和多张事实表有关系但是与这两个维度属性相关联的业务过程基本都是日志当中的业务过程。
CREATE EXTERNAL TABLE ods_log_inc
(common STRUCTar :STRING,ba :STRING,ch :STRING,is_new :STRING,md :STRING,mid :STRING,os :STRING,uid :STRING,vc:STRING COMMENT 公共信息,page STRUCTduring_time :STRING,item :STRING,item_type :STRING,last_page_id :STRING,page_id:STRING,source_type :STRING COMMENT 页面信息,actions ARRAYSTRUCTaction_id:STRING,item:STRING,item_type:STRING,ts:BIGINT COMMENT 动作信息,displays ARRAYSTRUCTdisplay_type :STRING,item :STRING,item_type :STRING,order :STRING,pos_id:STRING COMMENT 曝光信息,start STRUCTentry :STRING,loading_time :BIGINT,open_ad_id :BIGINT,open_ad_ms :BIGINT,open_ad_skip_ms:BIGINT COMMENT 启动信息,err STRUCTerror_code:BIGINT,msg:STRING COMMENT 错误信息,ts BIGINT COMMENT 时间戳
) COMMENT 活动信息表PARTITIONED BY (dt STRING)ROW FORMAT SERDE org.apache.hadoop.hive.serde2.JsonSerDeLOCATION /warehouse/gmall/ods/ods_log_inc/; 我们在创建日志表的时候已经把业务过程和维度属性给放到一起了没有必要再把维度属性 渠道、设备 再拆出来单独建个维度表。
1.2、维度表设计步骤
具体建模步骤看前面的博客数据仓库五【数据仓库建模】
1.2.1、确认维度 也就确认创建哪些维度表哪些维度属性不需要创建单独的维度表而是做维度退化我们上面都分析清楚了。
1.2.2、确定主维表和相关维表 主维表和相关维表指的都是和维度相关的业务系统当中的表然后通常情况下粒度最细的是主维表比如商品这个维度我们要去业务系统中找到和它相关的表发现有购物车表、订单表、商品信息表、退单表... 如果我们以订单表作为主维表那一个订单中可能有多个订单那就导致粒度太大我们无法确定商品的多个属性。所以我们尽可能选择粒度最细的比如商品信息表从商品信息表中我们可以得到更多和商品这个维度相关的属性。
1.2.3、确定维度属性 确定维度属性也就是确定维度表字段。维度属性可直接从主维表或相关维表中选择也可通过进一步加工得到。
1.3、商品维度表设计
1.3.1、确认维度 我们在上面回顾维度建模的时候已经确定维度了 准确说应该是给事实表确定维度我对这一步的理解是先清楚事实表需要这个维度我们才需要继续创建这张维度表。
1.3.2、确定主维表和相关维表 我们需要去业务系统寻找和商品相关的每张表 我们的 base_attr_info 存储的是平台属性名品牌、分类、内存、材质、CPU型号等都是平台属性名而 base_attr_value 存储的三星、6.4寸、8G内存、玻璃材质、骁龙888 等都是平台属性值。 一个平台属性值可能对应多个商品同样一个商品也有很多个平台属性值它们是多对多的关系平台属性和商品信息的关系存储在 sku_attr_value 这个中间表中。 上面都是我们和平台属性有关的表我们现在需要知道从应该这些表中获取哪些和商品相关的信息。其实我们主要希望得到的就是每个商品对应的平台属性名attr_id 和 value_name和平台属性值value_id 和 value_name而我们需要的这些字段都正好被存在了 sku_attr_value 这张中间表这张表并没有按照三范式去设计所以我们都不需要去通过 attr_id 和 value_id 去关联另外两张表去获取平台属性名和平台属性值。所以我们之前在做数据采集的时候其实也并没有对这两张表base_attr_value 和 base_attr_info 进行同步。 和平台属性一样一个商品属性值可能对应多个商品同样一个商品也有很多个销售属性值它们同样是多对多的关系商品属性和商品信息的关系存储在 sku_sale_attr_value 这个中间表中。而且它同样对 spu_sale_attr 和 spu_sale_attr_value 中的销售属性和销售属性值的字段进行了冗余我们采集的时候也没有进行同步而且在设计维度表的时候直接参 sku_sale_attr_value 这个中间表即可。 这样我们的主维表和相关维表就确定好了sku_info 是最细粒度的表所以 sku_info 就是主维表其它和商品相关的表都是相关维表。
1.3.3、确定商品维度的属性 确定商品维度属性就是确定商品维度表的字段商品主维表sku_info具有最细粒度的属性所以主维表的字段我们可以直接作为商品维度表的维度属性而其它的相关维表只需要取出它的 id 作为维度属性即可。
1.4、商品维度表的实现
1.4.1、建表语句
DROP TABLE IF EXISTS dim_sku_full;
CREATE EXTERNAL TABLE dim_sku_full
(id STRING COMMENT sku_id,price DECIMAL(16, 2) COMMENT 商品价格,sku_name STRING COMMENT 商品名称,sku_desc STRING COMMENT 商品描述,weight DECIMAL(16, 2) COMMENT 重量,is_sale BOOLEAN COMMENT 是否在售,spu_id STRING COMMENT spu编号,spu_name STRING COMMENT spu名称,category3_id STRING COMMENT 三级分类id,category3_name STRING COMMENT 三级分类名称,category2_id STRING COMMENT 二级分类id,category2_name STRING COMMENT 二级分类名称,category1_id STRING COMMENT 一级分类id,category1_name STRING COMMENT 一级分类名称,tm_id STRING COMMENT 品牌id,tm_name STRING COMMENT 品牌名称,sku_attr_values ARRAYSTRUCTattr_id :STRING,value_id :STRING,attr_name :STRING,value_name:STRING COMMENT 平台属性,sku_sale_attr_values ARRAYSTRUCTsale_attr_id :STRING,sale_attr_value_id :STRING,sale_attr_name :STRING,sale_attr_value_name:STRING COMMENT 销售属性,create_time STRING COMMENT 创建时间
) COMMENT 商品维度表PARTITIONED BY (dt STRING)STORED AS ORCLOCATION /warehouse/gmall/dim/dim_sku_full/TBLPROPERTIES (orc.compress snappy);
可以看到大部分的维度属性是来自于我们的主维表 剩下的字段来自我们的其它维表比如 SKU 相关的平台属性和销售属性
sku_attr_values ARRAYSTRUCTattr_id :STRING,value_id :STRING,attr_name :STRING,value_name:STRING COMMENT 平台属性,sku_sale_attr_values ARRAYSTRUCTsale_attr_id :STRING,sale_attr_value_id :STRING,sale_attr_name :STRING,sale_attr_value_name:STRING COMMENT 销售属性 其中sku_attr_values 存的是平台属性名和平台属性值sku_sale_attr_values 存的是销售属性名和销售属性值。这是我们前面维度表设计中提到的一个设计要点——多值属性对于多值属性通常有两种存储方案1. 多个属性值放到一个字段这也是我们这里用到的。2. 将多值属性放到多个字段这里我们没有用因为我们不能确定多值属性的属性个数所以就无法怎么去设计这个结构体。 至于这张全量表的分区我们选择用日期进行分区每天把前一天的数据都得导入到一个日期目录下。 这里我们选择 store as orc 来指定存储格式为 orc 使用 tblproperties 来指定压缩格式为 snappy。
4.1.2、装载语句 这张表的装载我们不能再用简单的 load 语句了因为我们现在不再是通过文件映射到表格了。我们得通过 insert select 来进行装载select 的当然就是我们的 ODS 层的原始数据表了而且 insert 时需要指定分区。 这就需要我们从 ODS 层中和我们商品相关的所有表主维表和相关维表中获取了而且是拿到这些表当天分区的数据然后写入到当天的维度表中。
-- 数据装载
-- 2020-06-14
-- sku_info 中的数据
selectid,spu_id,price,sku_name,sku_desc,weight,tm_id,category3_id,is_sale,create_time
from ods_sku_info_full
where dt2020-06-14;-- spu_info 中的数据
selectid,spu_name
from ods_spu_info_full
where dt2020-06-14;-- base_category3 中的数据,通过category2_id和base_category2产生关联
selectid,name,category2_id
from ods_base_category3_full
where dt2020-06-14;-- base_category2 中的数据,通过category1_id和base_category1产生关联
selectid,name,category1_id
from ods_base_category2_full
where dt2020-06-14;selectid,name
from ods_base_category1_full
where dt2020-06-14;selectid,tm_name
from ods_base_trademark_full
where dt2020-06-14;selectsku_id,
collect_set(named_struct(attr_id,attr_id,value_id,value_id,attr_name,attr_name,value_name,value_name))
from ods_sku_attr_value_full
where dt2020-06-14
group by sku_id;selectsku_id,
collect_set(named_struct(sale_attr_id,sale_attr_id,sale_attr_value_id,sale_attr_value_id,sale_attr_name,sale_attr_name,sale_attr_value_name,sale_attr_value_name)) sale_attrsfrom ods_sku_sale_attr_value_fullwhere dt2020-06-14group by sku_id;
对于平台属性名和平台属性值我们要把同一个 sku_id 的平台属性名和平台属性值放到同一个结构体数组中 selectsku_id,collect_set(named_struct(attr_id,attr_id,value_id,value_id,attr_name,attr_name,value_name,value_name))
from ods_sku_attr_value_full
where dt2020-06-14
group by sku_id; 销售属性名和销售属性值也是一样最后我们一共从这 8 张和商品信息相关的表中来获取我们需要的字段但是我们总不能就这么 join 吧那可读性太差了我们学习一种新的语法CTEcommon table expression
with
sku as
(selectid,price,sku_name,sku_desc,weight,is_sale,spu_id,category3_id,tm_id,create_timefrom ods_sku_info_fullwhere dt2020-06-14
),
spu as
(selectid,spu_namefrom ods_spu_info_fullwhere dt2020-06-14
),
c3 as
(selectid,name,category2_idfrom ods_base_category3_fullwhere dt2020-06-14
),
c2 as
(selectid,name,category1_idfrom ods_base_category2_fullwhere dt2020-06-14
),
c1 as
(selectid,namefrom ods_base_category1_fullwhere dt2020-06-14
),
tm as
(selectid,tm_namefrom ods_base_trademark_fullwhere dt2020-06-14
),
attr as
(selectsku_id,collect_set(named_struct(attr_id,attr_id,value_id,value_id,attr_name,attr_name,value_name,value_name)) attrsfrom ods_sku_attr_value_fullwhere dt2020-06-14group by sku_id
),
sale_attr as
(selectsku_id,collect_set(named_struct(sale_attr_id,sale_attr_id,sale_attr_value_id,sale_attr_value_id,sale_attr_name,sale_attr_name,sale_attr_value_name,sale_attr_value_name)) sale_attrsfrom ods_sku_sale_attr_value_fullwhere dt2020-06-14group by sku_id
)
insert overwrite table dim_sku_full partition(dt2020-06-14)
selectsku.id,sku.price,sku.sku_name,sku.sku_desc,sku.weight,sku.is_sale,sku.spu_id,spu.spu_name,sku.category3_id,c3.name,c3.category2_id,c2.name,c2.category1_id,c1.name,sku.tm_id,tm.tm_name,attr.attrs,sale_attr.sale_attrs,sku.create_time
from sku
left join spu on sku.spu_idspu.id
left join c3 on sku.category3_idc3.id
left join c2 on c3.category2_idc2.id
left join c1 on c2.category1_idc1.id
left join tm on sku.tm_idtm.id
left join attr on sku.idattr.sku_id
left join sale_attr on sku.idsale_attr.sku_id; 可以看到我们在 join 这 8 张表的时候先从我们的主维表sku去查询然后再和其它维表去 left join 来保证结果中包含所有的 sku 信息。而且我们可以看到每张表都能直接的通过和 sku 表中的字段或者间接的比如 1级category和2级category产生关联2级category再和3级category产生关联最后3级category直接和sku通过公共字段产生关联和我们的主维表产生关联。 而且我们这里用的是 insert overwrite为的是保持任务的幂等性比如说我们用 insert overwrite 执行这个任务多少次它的结果都是一样的也就不用担心执行过程失败重新执行时数据重复的问题但是如果我们用 insert into 的话我们这个分区的数据就可能会发生重复。
1.5、优惠券维度表
剩下的明天完成
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/87714.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!