SCD缓慢变化维,比如一个用户维表,用户属性会变化,但是不会变化很剧烈,可能一年只会变化一两次,也不会所有用户的属性都会有变化,只有少量的数据发生变化,所以叫缓慢变化维。这种问题就是由于维度的变化所造成的。

解决方式:

  • 是否保留历史数据
  • 保留多久历史数据
  • 历史状态如何与事实表关联

SCD1 保留最新状态

注册日期 用户编号 手机号码
2019-01-01 0001 111111
2019-01-01 0002 222222
2019-01-01 0003 333333
2019-01-01 0004 444444
注册日期 用户编号 手机号码 备注
2019-01-01 0001 111111 111111
2019-01-01 0002 233333 (由22222变成23333)
2019-01-01 0003 333333  
2019-01-01 0004 433333 (由44444变成43333)
2019-01-02 0005 555555 (2019-01-02新增)

缺点:没有任何历史状态,历史发生的事情无法追溯,企业中不关心历史状态的数据,可以使用SCD1

SCD2 保留所有历史状态

注册日期 用户编号 手机号码
2019-01-01 0001 111111
2019-01-01 0002 222222
2019-01-01 0003 333333
2019-01-01 0004 444444
注册日期 用户编号 手机号码 t_start_date t_end_date
2019-01-01 0001 111111 2019-01-01 9999-12-31
2019-01-01 0002 233333 2019-01-01 9999-12-31
2019-01-01 0003 333333 2019-01-01 2019-01-01
2019-01-01 0003 344444 2019-01-02 9999-12-31
2019-01-01 0004 433333 2019-01-01 9999-12-31
2019-01-02 0005 555555 2019-01-01 9999-12-31

出现问题:同一个用户编号的数据出现多次,与事实表关联时,每个订单就会被关联出多条记录,肯定会出错。

解决办法:加上时间限制条件,订单生成时间在用户表有效期内数据才做关联。

SCD3  只保留了最后一次变化记录,综合了SCD1和SCD2

注册日期 用户编号 手机号码
2019-01-01 0001 111111
2019-01-01 0002 222222
2019-01-01 0003 333333
2019-01-01 0004 444444
注册日期 用户编号 手机号码 先前手机号码
2019-01-01 0001 133333 111111
2019-01-01 0002 233333 222222
2019-01-01 0003 333333  
2019-01-01 0004 444444  

HIVE实现SCD2

如果关注历史状态基本上用SCD2,如果不关注历史状态就用SCD1,SCD3用得比较少。

SCD2

1,代理键:HIVE中如何实现自增ID

2,如何设计有效期时间

代理键的作用:给下表加一个代理ID,对于一个用户来说,如果状态发生3次变化,在这个表里有3条记录,分别有一个不同的ID。用代理键ID解决有效期问题。

除了在维表中有代理ID,在事实表里也会把用户ID用代理ID替换。关联的时候就不会出现数据重复的问题,就不需要根据有效期无能去做统计了。

注册日期 用户编号 手机号码 t_start_date t_end_date
2019-01-01 0001 111111 2019-01-01 9999-12-31
2019-01-01 0002 233333 2019-01-01 9999-12-31
2019-01-01 0003 333333 2019-01-01 2019-01-01
2019-01-01 0003 344444 2019-01-02 9999-12-31
2019-01-01 0004 433333 2019-01-01 9999-12-31
2019-01-02 0005 555555 2019-01-01 9999-12-31

有效期开始时间设计成一个很小的时间,在业务开始之前的时间;

有效期终止时间设计成一个非常大的值,一个固定的值。

Hive中的自增ID

  • 利用row_number()
  • org.apache.hadoop.hive.contrib.udf.UDFRowSequence

利用row_number()

select row_number() over(order by empno), empno from emp;

利用org.apache.hadoop.hive.contrib.udf.UDFRowSequence

hdfs dfs -mkdir /user/hive/lib
hdfs dfs -put ${HIVE_HOME}/lib/hive-contrib-1.2.1.jar /user/hive/lib/

添加Hive函数

hive>create temporary function row_sequence as 'org.apache.hadoop.hive.contrib.udf.UDFSequence';
hive>select row_sequence(), empno from emp limit 10;

添加Hive永久函数

hive>create function row_sequence as 'org.apache.hadoop.hive.contrib.udf.UDFSequence' using jar 'hdfs:///user/hive/lib/hive-contrib-1.2.1.jar';

准备数据

1,张三,US,CA
2,李四,US,CB
3,王五,CA,BB
4,赵六,CA,BC
5,老刘,AA,AA

创建用户表

-- 可以建成分区表 ,使用文本文件存储格式,因为后面用load加载数据,parquet格式的不支持

drop table if exists ods_user_update;

create table ods_user_update (
user_id INT,
name STRING,
cty STRING,
st STRING
)
COMMENT '每日用户更新表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'

建立用户维度表

-- 建立维度表 ,数据不能从外部文件加载,只能从一个hive表加载
create database test; use test; drop table if exists dim_user; CREATE TABLE dim_user (
surr_user_id bigint,
user_id INT,
name STRING,
cty STRING,
st STRING,
version INT,
ver_start_date DATE,
ver_end_date DATE)
COMMENT '每日维度表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'
STORED AS parquet
;

加载初始数据

-- parquet 的表不支持load 数据加载方式

load data local inpath '/root/test/user.txt' overwrite into table ods_user_update;

用户维度表加载初始数据

INSERT  INTO dim_user
SELECT
ROW_NUMBER() OVER (ORDER BY ods_user_update.user_id) + t2.sk_max,
ods_user_update.*,
1,
CAST('1900-01-01' AS DATE),
CAST('2200-01-01' AS DATE)
from ods_user_update CROSS JOIN (SELECT COALESCE(MAX(surr_user_id),0) sk_max FROM dim_user) t2;

更新维度表的数据

SET hivevar:pre_date = DATE_ADD(CURRENT_DATE(),-1);
SET hivevar:max_date = CAST('2200-01-01' AS DATE); load data local inpath '/root/test/user_update.txt' overwrite into table ods_user_update; INSERT OVERWRITE TABLE dim_user
SELECT * FROM
(
SELECT A.surr_user_id,
A.user_id,A.name,a.cty,a.st,a.version,
A.ver_start_date,
CASE
WHEN B.user_id IS NOT NULL and A.ver_end_date = ${hivevar:max_date} then ${hivevar:pre_date}
ELSE cast(A.ver_end_date as string)
END AS ver_end_date
FROM dim_user AS A LEFT JOIN ods_user_update AS B
ON A.user_id = B.user_id
UNION
select ROW_NUMBER() OVER (ORDER BY C.user_id) + D.sk_max,
c.user_id,c.name,c.cty,C.st,
0,
${hivevar:pre_date} AS ver_start_date,
${hivevar:max_date} AS ver_end_date
from ods_user_update as C cross join (SELECT COALESCE(MAX(surr_user_id),0) sk_max FROM dim_user) D
) AS T
;

HIVE- SCD缓慢变化的更多相关文章

  1. ODI 11g & 12c中缓慢变化维(SCD)的处理机制

    缓慢变化维(Slowly changing Dimensions)指的是维表中的维度字段值会随着时间或业务调整,而在后续的分析中,历史数据仍然要使用旧的维度值,新的数据会使用当前维度值.在数据仓库建设 ...

  2. 缓慢变化维 (Slowly changing dimension)

          维度建模的数据仓库中,有一个概念叫Slowly Changing Dimensions,中文一般翻译成"缓慢变化维",经常被简写为SCD.缓慢变化维的提出是因为在现实世 ...

  3. 缓慢变化维 (Slowly Changing Dimension) 常见的三种类型及原型设计(转)

    开篇介绍 在从 OLTP 业务数据库向 DW 数据仓库抽取数据的过程中,特别是第一次导入之后的每一次增量抽取往往会遇到这样的问题:业务数据库中的一些数据发生了更改,到底要不要将这些变化也反映到数据仓库 ...

  4. DataStage系列教程 (Slowly Changing Dimension)缓慢变化维

    BI中维表的增量更新一般有2种: Type 1:覆盖更改.记录的列值发生变化,直接update成最新记录. Type 2:历史跟踪更改.记录值发生变化,将该记录置为失效,再insert一条新的记录. ...

  5. DIV宽度自动缓慢变化

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. 使用CSS3的“transition ”属性控制长宽度的缓慢变化

    有时候我们可能会想要改变某个资源信息的长宽度,比如改变某个div的宽度,而且需要让这个宽度缓慢改变,而不是突然就改变了.这时候你可能会想到使用jquery的animate()函数,不过这个方法既得引用 ...

  7. 如何用SQL语句处理缓慢变化维(渐变维,拉链表)SCD-2?

    假设有一张居民维表,需要记录居民状态的变更历史,根据Kimball建模理论,设计居民维表如下: 另外在ODS中有居民信息的每日快照表(每天都记录一份居民的全量信息):O_USERINFO 如何将ODS ...

  8. 收集hive优化解决方案

    hive的优化问题1.启动一次JOB尽可能多做事,尽量减少job的数量.能重用就重用,要设计好的模型.2.合理设置reduce个数,reduce个数过多,会造成大量小文件问题.3.使用hive.exe ...

  9. 如何实现Qlikview的增量数据加载

    笔者备注: 刚刚接错Qlikview,上网搜集的资料,如何处理增量数据. 1 寻找增量时间戳(1)各种数据库:表的创建时间字段和修改时间字段或者最后的修改时间字段:(2)sql server:可以用找 ...

随机推荐

  1. The Thinking of AutomaticTest(有关自动化测试的思考)

    考虑因素: 容易维护 简洁易懂 代码重用性好 系统的稳定性强 UI自动化:   数据的获取:装载的数据文件类型.数据的形式.数据的解析方法定义. 1.利用Junit单元测试组织用例,明确输入数据.预期 ...

  2. Spoken English Practice(You know we can't afford that. How do other people do it? Other people make more twenty-four thousand a year. )

    绿色:连读:                  红色:略读:               蓝色:浊化:               橙色:弱读     下划线_为浊化 口语蜕变(2017/7/9) 英 ...

  3. 跳出NSDate

    感觉任何语言关于时间的格式化处理,时区的处理都是多的,最近被NSDate的各种问题坑了好久 先看看关于NSDate自己的问题 1.NSDate NSDate获取当前时间 NSDate *date=[N ...

  4. 第17章—前端分页(Bootstrap-Table)

    spring boot 系列学习记录:http://www.cnblogs.com/jinxiaohang/p/8111057.html 码云源码地址:https://gitee.com/jinxia ...

  5. Java IO异常处理方式

    public class IOException{ // 获取系统默认的行分隔符 private static final String LINE_SEPARATOR = System.getProp ...

  6. 9.Query on Embedded/Nested Documents-官方文档摘录

    1.插入案例 db.inventory.insertMany( [ { item: "journal", qty: 25, size: { h: 14, w: 21, uom: & ...

  7. Vue(3)- 安装脚手架、过滤器、生命周期的钩子函数、vue-router基本使用

    一.安装脚手架 1.下载node.js,本文下载版本为node-v8.12.0-x64.msi,一键式安装. 2.安装完成后,打开终端,输入node,可进入node环境(两次ctrl+c退出),如下图 ...

  8. linux c编程:记录锁

    记录锁相当于线程同步中读写锁的一种扩展类型,可以用来对有亲缘或无亲缘关系的进程进行文件读与写的同步,通过fcntl函数来执行上锁操作.尽管读写锁也可以通过在共享内存区来进行进程的同步,但是fcntl记 ...

  9. Oracle 11g数据库详解

    常见异常: ORA-14025:不能为实体化视图或实体化视图日志指定PARTITION ORA-14026:PARTITION和CLUSTER子句互相排斥 ORA-14027:仅可以指定一个PARTI ...

  10. Android图片加载框架Picasso最全使用教程1

    Picasso介绍 Picasso是Square公司开源的一个Android图形缓存库 A powerful image downloading and caching library for And ...