Hive/数据仓库_Hive 中如何生成代理键

前提:

       数仓中的维度,事实表技术提倡用代理键代替实体键,下面我们讲解下代理键的概念,以及Hive中如何生成代理键 (自增列)

 

代理键 :

      维度表中必须有一个能够唯一标识一行记录的列,通过该列维护维度表与事实表之间的关系,一般在维度表中业务主键符合条件可以当作维度主键。

 

补充:

      是由数据仓库处理过程中产生的,与业务本身无关的, 唯一标识维度表中一条记录并充当维度表主键的列,也是描述维度表与事实表关系的纽带。

所以在设计有代理键的维度表中,事实表中的关联键是代理键而不是原有的业务主键,即业务关系是靠代理键维护,这样有效避免源系统变化对数据仓库的影响。

在实际业务中,代理键通常是数值型,自增的值。

解决以下几类问题(部分问题):

1.当整合多个数据源的维度时,不同数据源的业务主键重复怎么办?

2.维度拉链表,同一主体对调记录,业务键重复如何去做

示例如下:

针对于多个数据源的数据。例如,下面两个不同来源的用户 :

 

技术部用户

Table S1

Id

name

note

1

Da1

Tech-leader

2

Jiang1

tech

 

财务部用户

Table S2

Id

name

note

1

Tian1

Finc-1

2

Tai

Finc-2

 

 

 

整合成如下数据

 

Table dim_user

Uid

id

name

note

source

1

1

Da1

Tech-leader

S1

2

2

Jiang1

tech

S1

3

1

Tian1

Finc-1

S2

4

2

Tai

Finc-2

S2

 

实现的几种方式:

1)UDF 实现自增列。

2)Hive 中实现自增键

 

下面我们主要讲解下如何在Hive 中实现自增键: 即方式二:

 

假设我们从 Table S1 ,Table S2 都是增量采集的数据

 

第一步 :增量采集数据,构建每天增量表

S1, S2  -> Tmp_s_inc

采集SQL :

S1 :

SELECT * FROM S1 WHERE created_time > ‘2018-06-01’

S2:

SELECT * FROM S2 WHERE created_time > ‘2018-06-01’

 

 

最终SQL :

INSERT OVERWRITE TABLE Tmp_s_inc  PARTITION( dt = ‘2018-06-01’)

SELECT

S1.*

,’S1’ AS source

FROM S1 WHERE created_time > ‘2018-06-01’

UNION ALL

SELECT

S2.*

,’S2’ AS source

FROM S2 WHERE created_time > ‘2018-06-01’

 

 

第二步:获取之前维度表,前一天的最大Uid (代理键), SQL 如下:

SELECT COALESCE(MAX(Uid, 0) FROM dim_user WHERE dt = ’2018-05-31 ’

 

 

第三步 :最终将生成的代理键的增量数据,结合前一天的数据插入到新的分区中:

INSERT OVERWRITE TABLE dim_user PARTITION (dt = ‘2018-06-01’)

SELECT

  ROW_NUMBER() OVER(ORDER BY id) + ta.max_id AS uid

  FROM tmp_s_inc AS tb

CROSS JOIN

(

       SELECT COALESCE(MAX(Uid, 0) FROM dim_user WHERE dt = ’2018-05-31’

) AS ta

UNION ALL

SELECT

  *

FROM dim_user WHERE dt = ‘2018-05-31’

;

 

 

 

 

额外延伸:

 

Hive 的CROSS JOIN :

Hive 中的CROSS JOIN ,为笛卡尔积。除非特殊需求,并且数据量不是特比的大的情况下,才可以慎用CROSS JOIN 。否则。很难跑出正确的结果,或者JOB 压根不能执行完。

 

Hive 中的连接

优化技巧:

Hive 中JOIN 的关键键必须在 ON() 中指定,不能在WHERE 中指定,否则就会先做笛卡尔积,再过滤

 

Hive 的ROW_NUMBER() OVER()

参考文章 :https://blog.csdn.net/u010003835/article/details/88179677

ROW_NUMBER() OVER ([partition BY COLUMN_A] ORDER BY COLUMN_B ASC/DESC) 

这个函数主要是用来分组排序的, 当不指定分组条件,则按照顺序递增

 

 

 

 

相关SQL :

建表构建数据:

CREATE TABLE IF NOT EXISTS tmp_S1 (
    id BIGINT 
    ,name STRING
    ,note STRING 
) PARTITIONED BY (
    pt STRING 
);


INSERT INTO TABLE tmp_S1 PARTITION (pt = '20190601')
VALUES (1, 's1-haha', 'CC'), (2, 's1-zk', 'CC');



CREATE TABLE IF NOT EXISTS tmp_S2 (
    id BIGINT 
    ,name STRING
    ,note STRING 
) PARTITIONED BY (
    pt STRING 
);


INSERT INTO TABLE tmp_S2 PARTITION (pt = '20190601')
VALUES (1, 's2-cx', 'CC'), (2, 's2-zk', 'CC');

 

从数据源导入增量表 ( 包含增量表建表语句)

CREATE TABLE IF NOT EXISTS tmp_S_inc (
    id BIGINT 
    ,name STRING
    ,note STRING 
    ,source STRING
) PARTITIONED BY (
    pt STRING 
);



INSERT OVERWRITE TABLE tmp_S_inc PARTITION (pt = '20190601')
SELECT 
    tmp_s1.id
    ,tmp_s1.name
    ,tmp_s1.note
    ,'S1' AS source  
FROM tmp_s1 
WHERE pt = '20190601'
UNION ALL 
SELECT 
    tmp_s2.id
    ,tmp_s2.name
    ,tmp_s2.note
    ,'S2' AS source  
FROM tmp_s2 
WHERE pt = '20190601'
;

 

从增量表导入目标表(包含目标表建表语句)

CREATE TABLE IF NOT EXISTS tmp_dim_S
(
    uid BIGINT,
    id BIGINT,
    name STRING,
    note STRING,
    source STRING 
)
PARTITIONED BY  
( 
    pt STRING 
);


-- SELECT COALESCE(MAX(uid), 0)
-- FROM tmp_dim_s 
-- WHERE pt = '20190531'
-- ;


INSERT OVERWRITE TABLE tmp_dim_S PARTITION (pt = '20190601')
SELECT 
  (ROW_NUMBER() OVER(ORDER BY ta.id) + max_uid) AS uid
  ,ta.*
FROM (
    SELECT 
        id
        ,name
        ,note
        ,source
    FROM tmp_S_inc
    WHERE pt = '20190601'
) AS ta
CROSS JOIN (
    SELECT COALESCE(MAX(uid), 0) AS max_uid
    FROM tmp_dim_S
    WHERE pt = '20190531' 
) AS tb 
UNION ALL 
SELECT 
    tmp_dim_S.uid
    ,tmp_dim_S.id
    ,tmp_dim_S.name
    ,tmp_dim_S.note
    ,tmp_dim_S.source
FROM tmp_dim_S
WHERE pt = '20190531'
;

 

 

 

发布了519 篇原创文章 · 获赞 1146 · 访问量 283万+

猜你喜欢

转载自blog.csdn.net/u010003835/article/details/104420508
今日推荐