定義:
拉鏈表 - 維護歷史狀態(tài),以及最新狀態(tài)數(shù)據(jù)的一種表,拉鏈表根據(jù)拉鏈粒度的不同,實際上相當(dāng)于快照,只不過做了優(yōu)化,去除了一部分不變的記錄而已,通過拉鏈表可以很方便的還原出拉鏈時點的客戶記錄。
拉鏈表通常是對賬戶信息的歷史變動進行處理保留的結(jié)果。
需求:
- 數(shù)據(jù)量比較大;
- 表中的部分字段會被update,如用戶的地址,產(chǎn)品的描述信息,訂單的狀態(tài)等等;
- 需要查看某一個時間點或者時間段的歷史快照信息,比如,查看某一個訂單在歷史某一個時間點的狀態(tài),
比如,查看某一個用戶在過去某一段時間內(nèi),更新過幾次等等; - 變化的比例和頻率不是很大,比如,總共有1000萬的會員,每天新增和發(fā)生變化的有10萬左右;
- 如果對這邊表每天都保留一份全量,那么每次全量中會保存很多不變的信息,對存儲是極大的浪費;
拉鏈歷史表,既能滿足反應(yīng)數(shù)據(jù)的歷史狀態(tài),又可以最大程度的節(jié)省存儲;
拉鏈表設(shè)計:
在企業(yè)中,由于有些流水表每日有幾千萬條記錄,數(shù)據(jù)倉庫保存5年數(shù)據(jù)的話很容易不堪重負(fù),因此可以使用拉鏈表的算法來節(jié)省存儲空間。
1.采集當(dāng)日全量數(shù)據(jù)存儲到 ND(當(dāng)日) 表中。
2.可從歷史表中取出昨日全量數(shù)據(jù)存儲到 OD(上日數(shù)據(jù))表中。
3.用ND-OD為當(dāng)日新增和變化的數(shù)據(jù)(即日增量數(shù)據(jù))。
兩個表進行全字段比較,將結(jié)果記錄到tabel_I表中
4.用OD-ND為狀態(tài)到此結(jié)束需要封鏈的數(shù)據(jù)。 (需要修改END_DATE)
兩個表進行全字段比較,將結(jié)果記錄到tabel_U表中
5.歷史表(HIS)比ND表和OD表多兩個字段(START_DATE,END_DATE)
6.將tabel_I表的內(nèi)容全部insert插入到HIS表中。START_DATE='當(dāng)日',END_DATE可設(shè)為'9999-12-31'
7.更新封鏈記錄的END_DATE
歷史表(HIS)和tabel_U表比較,START_DATE,END_DATE除外,以tabel_U表為準(zhǔn),兩者交集將其END_DATE改成當(dāng)日,說明該記錄失效。
8。取數(shù)據(jù)時對日期進行條件選擇即可,如:取20100101日的數(shù)據(jù)為
(where START_DATE<='20100101' and END_DATE>'20100101' )
例子 - 1:
假設(shè)以天為維度,以每天的最后一個狀態(tài)為當(dāng)天的最終狀態(tài)。
以一張訂單表為例,如下是原始數(shù)據(jù),每天的訂單狀態(tài)明細(xì)
1 2016-08-20 2016-08-20 創(chuàng)建
2 2016-08-20 2016-08-20 創(chuàng)建
3 2016-08-20 2016-08-20 創(chuàng)建
1 2016-08-20 2016-08-21 支付
2 2016-08-20 2016-08-21 完成
4 2016-08-21 2016-08-21 創(chuàng)建
1 2016-08-20 2016-08-22 完成
3 2016-08-20 2016-08-22 支付
4 2016-08-21 2016-08-22 支付
5 2016-08-22 2016-08-22 創(chuàng)建
根據(jù)拉鏈表我們希望得到的是
1 2016-08-20 2016-08-20 創(chuàng)建 2016-08-20 2016-08-20
1 2016-08-20 2016-08-21 支付 2016-08-21 2016-08-21
1 2016-08-20 2016-08-22 完成 2016-08-22 9999-12-31
2 2016-08-20 2016-08-20 創(chuàng)建 2016-08-20 2016-08-20
2 2016-08-20 2016-08-21 完成 2016-08-21 9999-12-31
3 2016-08-20 2016-08-20 創(chuàng)建 2016-08-20 2016-08-21
3 2016-08-20 2016-08-22 支付 2016-08-22 9999-12-31
4 2016-08-21 2016-08-21 創(chuàng)建 2016-08-21 2016-08-21
4 2016-08-21 2016-08-22 支付 2016-08-22 9999-12-31
5 2016-08-22 2016-08-22 創(chuàng)建 2016-08-22 9999-12-31
可以看出 1,2,3,4 每個訂單的狀態(tài)都有,并且也能統(tǒng)計到當(dāng)前的有效狀態(tài)。
例子 - 2:
舉個簡單例子,比如有一張訂單表,6月20號有3條記錄:
到6月21日,表中有5條記錄:
到6月22日,表中有6條記錄:
數(shù)據(jù)倉庫中對該表的保留方法:
只保留一份全量,則數(shù)據(jù)和6月22日的記錄一樣,如果需要查看6月21日訂單001的狀態(tài),則無法滿足;
每天都保留一份全量,則數(shù)據(jù)倉庫中的該表共有14條記錄,但好多記錄都是重復(fù)保存,沒有任務(wù)變化,如訂單002,004,數(shù)據(jù)量大了,會造成很大的存儲浪費;
如果在數(shù)據(jù)倉庫中設(shè)計成歷史拉鏈表保存該表,則會有下面這樣一張表:
說明:
dw_begin_date表示該條記錄的生命周期開始時間,dw_end_date表示該條記錄的生命周期結(jié)束時間;
dw_end_date = '9999-12-31'表示該條記錄目前處于有效狀態(tài);
如果查詢當(dāng)前所有有效的記錄,則select * from order_his where dw_end_date = '9999-12-31'
如果查詢2012-06-21的歷史快照,則select * from order_his where dw_begin_date <= '2012-06-21' and end_date >= '2012-06-21',這條語句會查詢到以下記錄:
和源表在6月21日的記錄完全一致:
可以看出,這樣的歷史拉鏈表,既能滿足對歷史數(shù)據(jù)的需求,又能很大程度的節(jié)省存儲資源。