前提:
データウェアハウスのディメンションであるファクトテーブルテクノロジは、エンティティキーではなく代理キーの使用を推奨しています。以下では、代理キーの概念と、Hiveで代理キーを生成する方法(自己増加列)について説明します。
代理キー:
レコードの行を一意に識別できる列がディメンションテーブルに存在する必要があります。この列は、ディメンションテーブルとファクトテーブルの間の関係を維持します。通常、ディメンションテーブルのビジネス主キーは、条件を満たす場合、ディメンション主キーと見なすことができます。
補足:
データウェアハウスプロセスによって生成され、ビジネス自体とは関係ありません。ディメンションテーブルのレコードを一意に識別し、ディメンションテーブルの主キーとして機能する列は、ディメンションテーブルとファクトテーブルの間の関係を説明するリンクでもあります。
したがって、サロゲートキー設計のディメンションテーブルでは、ファクトテーブルの関連キーは元のビジネス主キーではなくサロゲートキーです。つまり、ビジネス関係はサロゲートキーによって維持され、データウェアハウスに対するソースシステムの変更の影響を効果的に回避できます。
実際のビジネスでは、代理キーは通常、数値で自己増加型です。
次のタイプの問題(部分的な問題)を解決します。
1.複数のデータソースのディメンションを統合するときに、異なるデータソースのビジネス主キーが重複している場合はどうなりますか?
2.ジッパーテーブルのディメンション、同じ件名のスワップレコード、ビジネスキーの複製方法
次に例を示します。
複数のデータソースのデータ。たとえば、異なるソースの次の2人のユーザー:
技術部門ユーザー
テーブルS1
Id |
名前 |
注意 |
1 |
Da1 |
技術リーダー |
2 |
江1 |
ハイテク |
財務部門のユーザー
テーブルS2
Id |
名前 |
注意 |
1 |
Tian1 |
ファイン-1 |
2 |
若しくは |
ファイン-2 |
次のデータに統合する
テーブルdim_user
Uid |
id |
名前 |
注意 |
ソース |
1 |
1 |
Da1 |
技術リーダー |
S1 |
2 |
2 |
江1 |
ハイテク |
S1 |
3 |
1 |
Tian1 |
ファイン-1 |
S2 |
4 |
2 |
若しくは |
ファイン-2 |
S2 |
達成するいくつかの方法:
1)UDFは自己増加カラムを実現します。
2)Hiveで自己増加キーを実装する
以下では、主にHiveで自動インクリメントキーを実装する方法について説明します。つまり、方法2です。
テーブルS1およびテーブルS2からデータを段階的に収集するとします。
ステップ1:データを増分的に収集し、毎日の増分テーブルを作成する
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’
ステップ2:前のディメンションテーブル、前日の最大Uid(代理キー)を取得します。SQLは次のとおりです。
SELECT COALESCE(MAX(Uid, 0) FROM dim_user WHERE dt = ’2018-05-31 ’
3番目のステップ:最後に、生成されたサロゲートキーの増分データが前日のデータと組み合わされて新しいパーティションに入れられます。
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のキーは、WHEREではなくON()で指定する必要があります。それ以外の場合は、最初にデカルト積、次にフィルターになります。
ハイブ的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'
;