Hive --- ジッパー テーブルの設計と実装

1 データ同期の問題

実際の業務では、Hive は主にオフライン データ ウェアハウスを構築し、さまざまなデータ ソースから定期的にデータを Hive に収集し、階層変換を通じてデータ アプリケーションを提供するために使用されます。例えば、注文分析やユーザー分析のために、MySQLから最新の注文情報やユーザー情報、店舗情報などを毎日データウェアハウスに同期する必要があります。

 

 例: MySQL にユーザー テーブル tb_user があり、各ユーザーが登録されると、ユーザーの情報がユーザー テーブルに追加されます。

 

ユーザーは毎日登録し、新しいユーザー情報が生成されるため、MySQL 内のユーザー データは毎日 Hive データ ウェアハウスに同期する必要があります。

1日にhiveにテーブルを作成してデータをpullしましたが、2日にMySQLに新規ユーザー登録データが2件追加され、ユーザーデータが1件更新されたとします。

 

 次に、2 番のデータを Hive に同期する必要があります。新しいデータは Hive テーブルに直接読み込まれますが、更新されたデータはどのように Hive テーブルに保存されるのでしょうか?

 オプション 1: 直接取材

2 番のデータを使用して 1 番のデータを直接上書きする
長所: 最もシンプルな実装で最も使いやすい
短所: 履歴ステータスがなく、008 より前のデータをクエリしたい場合は参照できないそれ。

 オプション 2: 日付に基づいて完全なスナップショット テーブルを構築する

 1 日にテーブルを作成してすべてのデータを取得する
2 日に別のテーブルを作成してすべてのデータを取得する 
... 毎日テーブルを作成する
利点: さまざまな時点でのすべてのデータの状態が記録される 欠点:
多くのデータが記録される冗長ストレージは発生しませんでした。データを変更すると、データの過剰なストレージが発生します。

 オプション 3: ジッパー テーブルを構築し、経時的に変更されたデータの各状態の期間をマークします。

 

 ジッパー テーブルの設計は、更新されたデータのステータスを記録することです。更新されていないデータはステータスに格納されません。異なる時点でのすべてのデータのすべてのステータスを格納するために使用されます。各ステータスのライフ サイクルは次のとおりです。クエリを実行すると、指定した時間範囲のステータスのデータを要求に応じて取得できます。デフォルトでは、9999-12-31 などの最大値が最新のステータスを表すために使用されます。

2. ジッパーテーブルの実装原理

 

 1. 変更されたデータを増分収集し、増分テーブルに格納します。

 

2. Hiveのジッパーテーブルと一時テーブルのデータをマージし、マージ結果を一時テーブルに書き込む

3. テンポラリテーブルのデータをジッパーテーブルに上書きします

3 ジッパーテーブル実装デモンストレーション

 zip リストを作成する

-- データ準備
vizipper.txt
001 186xxxx1234 laoda 0 sh 2021-01-01 9999-12-31
002 186xxxx1235 laoer 1 bj 2021-01-01 9999-12-31
003 186xxxx1236 laosan 0 sz 2021 - 01-01 9999- 12-31
004 186xxxx1237 laosi 1 gz 2021-01-01 9999-12-31
005 186xxxx1238 laowu 0 sh 2021-01-01 9999-12-31
006 186xxxx1239 laoliu 1 bj 2021-01-0 1 9999-12-31
007 186xxxx1240 laoqi 0 sz 2021-01-01 9999-12-31
008 186xxxx1241 laova 1 gz 2021-01-01 9999-12-31
009 186xxxx1242 laojiu 0 sh 2021-01-01 9999-12 -31
010 186xxxx1243 老師 1 bj 2021 - 01-01 9999-12-31

--创建拉链表
create table dw_zipper
(
    userid    string,
    phone     string,
    nick      string,
    gender    int,
    addr      string,
    starttime string,
    endtime   string
) row format delimited fields terminated by '\t';
load data local inpath '/root/zipper.txt' into table dw_zipper;
select * from dw_zipper;

 デルタテーブルの作成

vi update.txt
008 186xxxx1241 laoba 1 sh 2021-01-02 9999-12-31
011 186xxxx1244 laoshi 1 jx 2021-01-02 9999-12-31
012 186xxxx1245 laoshi 0 zj 2021-01-0 2 9999-12-31

 

create table ods_update
(
    userid    string,
    phone     string,
    nick      string,
    gender    int,
    addr      string,
    starttime string,
    endtime   string
) row format delimited fields terminated by '\t';

load data local inpath '/root/update.txt' overwrite into table ods_update;

select * from ods_update;

一時テーブルを作成する

create table tmp_zipper
(
    userid    string,
    phone     string,
    nick      string,
    gender    int,
    addr      string,
    starttime string,
    endtime   string
) row format delimited fields terminated by '\t';

 データを一時テーブルにマージする

insert overwrite table tmp_zipper
select
    userid,
    phone,
    nick,
    gender,
    addr,
    starttime,
    endtime
from ods_update
union all
--查询原来拉链表的所有数据,并将这次需要更新的数据的endTime更改为更新值的startTime
select
    a.userid,
    a.phone,
    a.nick,
    a.gender,
    a.addr,
    a.starttime,
    --如果这条数据没有更新或者这条数据不是要更改的数据,就保留原来的值,否则就改为新数据的开始时间-1
    if(b.userid is null or a.endtime < '9999-12-31', a.endtime , date_sub(b.starttime,1)) as endtime
from dw_zipper a  left join ods_update b
                            on a.userid = b.userid ;

ジッパーテーブルデータを上書きする

insert overwrite table dw_zipper
select * from tmp_zipper;

おすすめ

転載: blog.csdn.net/m0_53400772/article/details/130828882