數(shù)倉--DW--Hadoop數(shù)倉實(shí)踐Case-16-遲到的事實(shí)

遲到的事實(shí)概述

  • 數(shù)據(jù)倉庫通常建立于一種理想的假設(shè)情況下, 這就是數(shù)據(jù)倉庫的度量(事實(shí)記錄) 與度量的環(huán)境(維度記錄) 同時(shí)出現(xiàn)在數(shù)據(jù)倉庫中。 當(dāng)同時(shí)擁有事實(shí)記錄和正確的當(dāng)前維度行時(shí)窃这, 就能夠從容地首先維護(hù)維度鍵, 然后在對應(yīng)的事實(shí)表行中使用這些最新的鍵。 然而须喂, 各種各樣的原因會(huì)導(dǎo)致需要ETL系統(tǒng)處理遲到的事實(shí)數(shù)據(jù)匹涮。 例如天试, 某些線下的業(yè)務(wù), 數(shù)據(jù)進(jìn)入操作型系統(tǒng)的時(shí)間會(huì)滯后于事務(wù)發(fā)生的時(shí)間然低。 再或者出現(xiàn)某些極端情況喜每, 如源數(shù)據(jù)庫系統(tǒng)出現(xiàn)故障, 直到恢復(fù)后才能補(bǔ)上故障期間產(chǎn)生的數(shù)據(jù)雳攘。
  • 在銷售訂單示例中带兜, 晚于訂單日期進(jìn)入源數(shù)據(jù)的銷售訂單可以看作是一個(gè)遲到事實(shí)的例子。 銷售訂單數(shù)據(jù)被裝載進(jìn)其對應(yīng)的事實(shí)表時(shí)吨灭, 裝載日期晚于銷售訂單產(chǎn)生的日期刚照, 因此是一個(gè)遲到的事實(shí)。 本例中因?yàn)槎ㄆ谘b載的是前一天的數(shù)據(jù)喧兄, 所以這里的“晚于”指的是事務(wù)數(shù)據(jù)延遲兩天及其以上才到達(dá)ETL系統(tǒng)无畔。
  • 必須對標(biāo)準(zhǔn)的ETL過程進(jìn)行特殊修改以處理遲到的事實(shí)。 首先吠冤, 當(dāng)遲到度量事件出現(xiàn)時(shí)浑彰, 不得不反向搜索維度表歷史記錄, 以確定事務(wù)發(fā)生時(shí)間點(diǎn)的有效的維度代理鍵拯辙, 因?yàn)楫?dāng)前的維度內(nèi)容無法匹配輸入行的情況郭变。 此外, 還需要調(diào)整后續(xù)事實(shí)行中的所有半可加度量涯保, 例如饵较, 由于遲到的事實(shí)導(dǎo)致客戶當(dāng)前余額的改變。 遲到事實(shí)可能還會(huì)引起周期快照事實(shí)表的數(shù)據(jù)更新遭赂。 例如 數(shù)倉--DW--Hadoop數(shù)倉實(shí)踐Case-13-周期快照事實(shí)表節(jié)討論的月銷售周期快照表循诉, 如果2016年6月的銷售訂單金額已經(jīng)計(jì)算并存儲在month_end_sale_order_fact快照表中, 這時(shí)一個(gè)遲到的6月訂單在7月某天被裝載撇他, 那么2016年6月的快照金額必須因遲到事實(shí)而重新計(jì)算茄猫。
  • 下面就以銷售訂單數(shù)據(jù)倉庫為例, 說明如何處理遲到的事實(shí)困肩。

修改數(shù)據(jù)倉庫模式

  • 借助 數(shù)倉--DW--Hadoop數(shù)倉實(shí)踐Case-13-周期快照事實(shí)表中建立的月度周期快照表划纽,其數(shù)據(jù)源自已經(jīng)處理過的銷售訂單事務(wù)事實(shí)表。 因此為了確定事實(shí)表中的一條銷售訂單記錄是否是遲到的锌畸, 需要把源數(shù)據(jù)中的登記日期列裝載進(jìn)銷售訂單事實(shí)表勇劣。 為此要在銷售訂單事實(shí)表上添加登記日期代理鍵列。 為了獲取登記日期代理鍵的值, 還要使用維度角色扮演技術(shù)添加登記日期維度表比默。
  • 執(zhí)行下面的腳本在銷售訂單事實(shí)表里添加名為entry_date_sk的日期代理鍵列幻捏, 并且從日期維度表創(chuàng)建一個(gè)叫做entry_date_dim的數(shù)據(jù)庫視圖。
use dw;
-- 在事務(wù)事實(shí)表中添加登記日期代理鍵列
alter table
    sales_order_fact rename to sales_order_fact_old;
-- 創(chuàng)建表
create table
    sales_order_fact
(
order_number int comment'order number',
customer_sk int comment'customer SK',
customer_zip_code_sk int comment'customer zip code SK',
shipping_zip_code_sk int comment'shipping zip code SK',
product_sk int comment'product SK',
sales_order_attribute_sk int comment'sales order attribute SK',
order_date_sk int comment'order date SK',
entry_date_sk int comment 'entry date SK',
allocate_date_sk int comment'allocate date SK',
allocate_quantity int comment'allocate quantity',
packing_date_sk int comment'packing date SK',
packing_quantity int comment'packing quantity',
ship_date_sk int comment'ship date SK',
ship_quantity int comment'ship quantity',
receive_date_sk int comment'receive date SK',
receive_quantity int comment'receive quantity',
request_delivery_date_sk int comment'request delivery date SK',
order_amount decimal(10,2) comment'order amount',
order_quantity int comment'order quantity'
) 
clustered by(order_number) into8 buckets
stored as
orc tblproperties ('transactional'='true');
-- 將數(shù)據(jù)插入到表中
insert into
sales_order_fact
select
order_number,
customer_sk,
customer_zip_code_sk,
shipping_zip_code_sk,
product_sk,
sales_order_attribute_sk,
order_date_sk,
null,
allocate_date_sk,
allocate_quantity,
packing_date_sk,
packing_quantity,
ship_date_sk,
ship_quantity,
receive_date_sk,
receive_quantity,
request_delivery_date_sk,
order_amount,
order_quantity
fromsales_order_fact_old;
drop table
sales_order_fact_old;
-- 建立登記日期維度視圖
create view
entry_date_dim
(entry_date_sk, entry_date, month_name, month
, quarter, year
)
as select
date_sk, date, month_name, month, quarter, year
from
date_dim
;

修改定期裝載腳本

  • 在創(chuàng)建了登記日期維度視圖命咐, 并給銷售訂單事實(shí)表添加了登記日期代理鍵列以后篡九, 需要修改數(shù)據(jù)倉庫定期裝載腳本來裝載登記日期。 下面顯示了修改后的regular_etl.sql定期裝載腳本(只列出修改的部分) 醋奠。 注意sale_order源數(shù)據(jù)表及其對應(yīng)的過渡表中都已經(jīng)含有登記日期榛臼, 只是以前沒有將其裝載進(jìn)數(shù)據(jù)倉庫。
-- 修改定期裝載腳本
insert into
    sales_order_fact
select
    a.order_number,
    c.customer_sk,
    i.customer_zip_code_sk,
    j.shipping_zip_code_sk,
    d.product_sk,
    g.sales_order_attribute_sk,
    e.order_date_sk,
    h.entry_date_sk,
    null, null, null, null, null, null, null, null,
    f.request_delivery_date_sk,
    order_amount,
    quantity
from
    rds.sales_order a,
    customer_dim c,
    product_dim d,
    order_date_dim e,
    request_delivery_date_dim f,
    sales_order_attribute_dim g,
    customer_zip_code_dim i,
    shipping_zip_code_dim j,
    entry_date_dim h,
    rds.customer k,
    rds.cdc_time l
where
    a.order_status = 'N'
and
    a.customer_number = c.customer_number
and
    a.status_date >= c.effective_date
and 
    a.status_date < c.expiry_date
and
    a.customer_number = k.customer_number
and
    k.customer_zip_code = i.customer_zip_code
and
    a.status_date >= i.effective_date
and
    a.status_date <= i.expiry_date
and
    k.shipping_zip_code = j.shipping_zip_code
and
    a.status_date >= j.effective_date
and
    a.status_date <= j.expiry_date
and
    a.product_code = d.product_code
and
    a.status_date >= d.effective_date
and
    a.status_date < d.expiry_date
and to_date
    (a.status_date) = e.order_date
and 
    to_date(a.entry_date) = h.entry_date
and 
    to_date(a.request_delivery_date) = f.request_delivery_date
and
    a.verification_ind = g.verification_ind
and
    a.credit_check_flag = g.credit_check_flag
and
    a.new_customer_ind = g.new_customer_ind
and
    a.web_order_flag = g.web_order_flag
and
    a.entry_date >= l.last_load 
and a.entry_date < l.current_load ;
-- 更新分配庫房窜司、 打包沛善、 配送、 收貨4種訂單狀態(tài)的時(shí)間代理鍵和度量塞祈,
-- 也要加上entry_date_sk
  • 本節(jié)開頭曾經(jīng)提到路呜, 需要為遲到的事實(shí)行獲取事務(wù)發(fā)生時(shí)間點(diǎn)的有效的維度代理鍵。 在裝載腳本中使用銷售訂單過渡表的狀態(tài)日期字段限定當(dāng)時(shí)的維度代理鍵织咧。 例如胀葱, 為了獲取事務(wù)發(fā)生時(shí)的客戶代理鍵, 篩選條件為:
status_date >= customer_dim.effective_date
and
status_date < customer_dim.expiry_date
  • 之所以可以這樣做笙蒙, 原因在于本示例滿足以下兩個(gè)前提條件: 在最初源數(shù)據(jù)庫的銷售訂單表中抵屿, status_date存儲的是狀態(tài)發(fā)生時(shí)的時(shí)間; 維度的生效時(shí)間與過期時(shí)間構(gòu)成一條連續(xù)且不重疊的時(shí)間軸捅位, 任意status_date日期只能落到唯一的生效時(shí)間轧葛、 過期時(shí)間區(qū)間內(nèi)。

修改裝載月度周期快照事實(shí)表

  • 數(shù)倉--DW--Hadoop數(shù)倉實(shí)踐Case-13-周期快照事實(shí)表創(chuàng)建的month_sum.sql腳本文件用于裝載月銷售周期快照事實(shí)表艇搀。 遲到的事實(shí)記錄會(huì)對周期快照中已經(jīng)生成的月銷售匯總數(shù)據(jù)產(chǎn)生影響尿扯, 因此必須做適當(dāng)?shù)男薷摹?/li>
  • 月銷售周期快照表存儲的是某月某產(chǎn)品匯總的銷售數(shù)量和銷售金額, 表中有月份代理鍵焰雕、 產(chǎn)品代理鍵衷笋、 銷售金額、 銷售數(shù)量4個(gè)字段矩屁。 由于遲到事實(shí)的出現(xiàn)辟宗, 需要將事務(wù)事實(shí)表中的數(shù)據(jù)劃分為三類: 非遲到的事實(shí)記錄; 遲到的事實(shí)吝秕, 但周期快照表中尚不存在相關(guān)記錄泊脐; 遲到的事實(shí), 并且周期快照表中已經(jīng)存在相關(guān)記錄烁峭。 對這三類事實(shí)數(shù)據(jù)的處理邏輯各不相同容客, 前兩類數(shù)據(jù)需要匯總后插入快照表秕铛, 而第三種情況需要更新快照表中的現(xiàn)有數(shù)據(jù)。 下面我們對修改后的month_sum.sql文件分解說明缩挑。
drop table if exists tmp;
create table tmp as
select a.order_month_sk order_month_sk,
a.product_sk product_sk,
a.month_order_amount + b.order_amount month_order_amount,
a.month_order_quantity + b.order_quantity month_order_quantity
from month_end_sales_order_fact a,
(select d.month_sk month_sk,
a.product_sk product_sk,
sum(order_amount) order_amount,
sum(order_quantity) order_quantity
from sales_order_fact a,
order_date_dim b,
entry_date_dim c,
month_dim d
where a.order_date_sk = b.order_date_sk
and a.entry_date_sk = c.entry_date_sk
and c.month = month(${hivevar:pre_month_date})
and c.year = year(${hivevar:pre_month_date})
and b.month = d.month
and b.year = d.year
and b.order_date <> c.entry_date
group by d.month_sk , a.product_sk) b
where a.product_sk = b.product_sk
and a.order_month_sk = b.month_sk;
delete from month_end_sales_order_fact
where exists
(select 1
from tmp t2
where month_end_sales_order_fact.order_month_sk = t2.order_month_sk
and month_end_sales_order_fact.product_sk = t2.product_sk);
insert into month_end_sales_order_fact select * from tmp;
  • 按事務(wù)發(fā)生時(shí)間的先后順序但两, 我們先處理第三種情況。 為了更新周期快照表數(shù)據(jù)调煎, 需要?jiǎng)?chuàng)建一個(gè)臨時(shí)表镜遣。 子查詢用于從銷售訂單事實(shí)表中獲取所有上個(gè)月錄入的己肮, 并且是遲到的數(shù)據(jù)行的匯總士袄, 用b.order_date <> c.entry_date作為判斷遲到的條件。 本示例中實(shí)際可以去掉這條判斷語句谎僻, 因?yàn)橹挥羞t到事實(shí)會(huì)對已有的快照數(shù)據(jù)造成影響娄柳。 外層查詢把具有相同產(chǎn)品代理鍵和月份代理鍵的遲到事實(shí)的匯總數(shù)據(jù)加到已有的快照數(shù)據(jù)行上, 臨時(shí)表中存儲這個(gè)查詢的結(jié)果艘绍。 注意產(chǎn)品代理鍵和月份代理鍵共同構(gòu)成了周期快照表的邏輯主鍵赤拒, 可以唯一標(biāo)識一條記錄; 之后使用先刪除再插入的方式更新周期快照表诱鞠。 從周期快照表刪除數(shù)據(jù)的操作也是以邏輯主鍵匹配作為過濾條件挎挖。
insert into
    month_end_sales_order_fact
select
    d.month_sk, a.product_sk, sum(order_amount), sum(order_quantity)
from
    sales_order_fact a,
    order_date_dim b,
    entry_date_dim c,month_dim d
where
    a.order_date_sk = b.order_date_sk
and
    a.entry_date_sk = c.entry_date_sk
and
    c.month= month(${hivevar:pre_month_date})
and
    c.year= year(${hivevar:pre_month_date})
and
    b.month= d.month
and
    b.year= d.year
and 
    not exists
    (select
        1
    from
        month_end_sales_order_fact p
    where
        p.order_month_sk = d.month_sk
    and
    p.product_sk = a.product_sk)
group by
    d.month_sk , a.product_sk
;
  • 上面這條語句將第一、 二類數(shù)據(jù)統(tǒng)一處理航夺。 使用相關(guān)子查詢獲取所有上個(gè)月新錄入的蕉朵, 并且在周期快照事實(shí)表中尚未存在的產(chǎn)品銷售月匯總數(shù)據(jù), 插入到周期快照表中阳掐。 銷售訂單事實(shí)表的粒度是每天始衅, 而周期快照事實(shí)表的粒度是每月, 因此必須使用訂單日期代理鍵對應(yīng)的月份代理鍵進(jìn)行比較缭保。

遲到的事實(shí)總結(jié)

  • 遲到的事實(shí)似乎是針對周期性快照事實(shí)表才需要處理的汛闸?
  • 這個(gè)遲到的事實(shí)需要在模型建立的時(shí)候考慮進(jìn)去,模型建立之初需要事實(shí)考慮的艺骂。
  • 數(shù)倉模型的建立很考驗(yàn)實(shí)力啊诸老。
  • 還是對模型多思考才行。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钳恕,一起剝皮案震驚了整個(gè)濱河市孕锄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌苞尝,老刑警劉巖畸肆,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宙址,居然都是意外死亡轴脐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來大咱,“玉大人恬涧,你說我怎么就攤上這事〔杲恚” “怎么了溯捆?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長厦瓢。 經(jīng)常有香客問我提揍,道長,這世上最難降的妖魔是什么煮仇? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任劳跃,我火速辦了婚禮,結(jié)果婚禮上浙垫,老公的妹妹穿的比我還像新娘刨仑。我一直安慰自己,他們只是感情好夹姥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布杉武。 她就那樣靜靜地躺著,像睡著了一般辙售。 火紅的嫁衣襯著肌膚如雪轻抱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天圾亏,我揣著相機(jī)與錄音十拣,去河邊找鬼。 笑死志鹃,一個(gè)胖子當(dāng)著我的面吹牛夭问,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曹铃,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缰趋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陕见?” 一聲冷哼從身側(cè)響起秘血,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎评甜,沒想到半個(gè)月后灰粮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忍坷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年粘舟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熔脂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柑肴,死狀恐怖霞揉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晰骑,我是刑警寧澤适秩,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站硕舆,受9級特大地震影響秽荞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岗宣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一蚂会、第九天 我趴在偏房一處隱蔽的房頂上張望淋样。 院中可真熱鬧耗式,春花似錦、人聲如沸趁猴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽儡司。三九已至娱挨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捕犬,已是汗流浹背跷坝。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碉碉,地道東北人柴钻。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像垢粮,于是被迫代替她去往敵國和親贴届。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容