拉鏈表是數(shù)據(jù)倉(cāng)庫(kù)中一種重要的模型,相信很多數(shù)據(jù)工作者都接觸過(guò),面試也是經(jīng)??疾斓狞c(diǎn)。
但是很多人第一次接觸“拉鏈表”這個(gè)詞,難免會(huì)產(chǎn)生疑惑:拉鏈表是什么?
什么是拉鏈表
按照度娘的解釋?zhuān)骸袄湵硎且环N針對(duì)數(shù)據(jù)倉(cāng)庫(kù)設(shè)計(jì)中表存儲(chǔ)數(shù)據(jù)的方式而定義的數(shù)據(jù)模型,它有點(diǎn)類(lèi)似于快照,用于維護(hù)歷史狀態(tài)及最新?tīng)顟B(tài)數(shù)據(jù)?!?/p>
這么看還是有點(diǎn)難理解,既然如此,那我們先不管,先來(lái)看以下場(chǎng)景:
- 假如有張表如表1-1所示,每天的數(shù)據(jù)量大概有50w
- 表中有些字段會(huì)被 update,如表1-2,且每天更新的數(shù)據(jù)量很小,大約只有5k
- 有些報(bào)表需要查看歷史某個(gè)日期的數(shù)據(jù)
- 存儲(chǔ)空間有限,需要盡可能的節(jié)約存儲(chǔ)空間
問(wèn):你會(huì)怎么將其裝入數(shù)倉(cāng)中?
表1-1:
id | name | phone |
---|---|---|
1 | Agnes | 123 |
2 | Max | 456 |
3 | Tony | 789 |
… | … | … |
表1-2:
id | name | phone |
---|---|---|
1 | Agnes | 123 |
2 | Max | 456 |
3 | Tony | 321 |
… | … | … |
每天追加一份全量數(shù)據(jù)
這種方式比較簡(jiǎn)單粗暴,如表1-3,不僅操作方便,還可以反映歷史變化。但是弊端也很明顯:存在數(shù)據(jù)冗余、浪費(fèi)存儲(chǔ)空間。
每天50w,一個(gè)月就有1500w了,時(shí)間越長(zhǎng),數(shù)據(jù)量越多,然而實(shí)際變化的數(shù)據(jù)每天只有5k,剩下的數(shù)據(jù)幾乎都是重復(fù)存儲(chǔ)的,極大浪費(fèi)存儲(chǔ)空間。
表1-3
id | name | phone |
---|---|---|
1 | Agnes | 123 |
2 | Max | 456 |
3 | Tony | 789 |
1 | Agnes | 123 |
2 | Max | 456 |
3 | Tony | 321 |
… | … | … |
直接覆蓋原來(lái)的數(shù)據(jù)
這種方式也很簡(jiǎn)單,直接全表 truncate 再 insert,雖然空間節(jié)省了,但缺點(diǎn)也很明顯,會(huì)把歷史數(shù)據(jù)覆蓋掉,沒(méi)辦法反映歷史數(shù)據(jù)的變化。
使用拉鏈表
在原表結(jié)構(gòu)的基礎(chǔ)上,加兩個(gè)字段:start_date 和 end_date,第一次抽取數(shù)據(jù)的時(shí)候,將 start_date 初始化為抽取日期,end_date 初始化為永久日期,如表1-4所示
表1-4:
id | name | phone | start_date | end_date |
---|---|---|---|---|
1 | Agnes | 123 | 20230328 | 99999999 |
2 | Max | 456 | 20230328 | 99999999 |
3 | Tony | 789 | 20230328 | 99999999 |
… | … | … | … | … |
之后的每一次抽取,則需要對(duì)比當(dāng)日數(shù)據(jù)以及歷史數(shù)據(jù),將有變化的歷史數(shù)據(jù)的 end_date 改成當(dāng)日抽取日期;
將新抽取的有變化的數(shù)據(jù)按照初始化的方式設(shè)置 start_date 和 end_date。如表1-5所示
表1-5:
id | name | phone | start_date | end_date |
---|---|---|---|---|
1 | Agnes | 123 | 20230328 | 99999999 |
2 | Max | 456 | 20230328 | 99999999 |
3 | Tony | 789 | 20230328 | 20230329 |
3 | Tony | 321 | 20230329 | 99999999 |
… | … | … | … | … |
這種數(shù)據(jù)模型就是拉鏈表,它既能反映歷史變化,又能節(jié)省空間,豈不美哉?
如何實(shí)現(xiàn)拉鏈表
既然理解了什么是拉鏈表,那么應(yīng)該如何實(shí)現(xiàn)呢?
方式一
(1)獲取當(dāng)日數(shù)據(jù);
(2)比較當(dāng)日數(shù)據(jù)及歷史數(shù)據(jù),找出新增和變化的數(shù)據(jù),存到臨時(shí)表,并將開(kāi)始日期置為當(dāng)前日期,結(jié)束日期置為最大日期;
(3)將歷史數(shù)據(jù)表中的變化數(shù)據(jù)的結(jié)束日期更新為當(dāng)前日期,即閉鏈;
(4)將臨時(shí)表的新增和變化數(shù)據(jù)插入歷史數(shù)據(jù)表中,即開(kāi)鏈。
方式二
(1)獲取當(dāng)日數(shù)據(jù);
(2)比較當(dāng)日數(shù)據(jù)和昨日數(shù)據(jù),找出新增數(shù)據(jù)和變化后數(shù)據(jù);
(3)比較昨日數(shù)據(jù)和當(dāng)日數(shù)據(jù),找出刪除數(shù)據(jù)和變化前數(shù)據(jù);
(4)刪除歷史數(shù)據(jù)表中的刪除數(shù)據(jù)和變化前數(shù)據(jù);
(5)將新增數(shù)據(jù)和變化后數(shù)據(jù)插入歷史數(shù)據(jù)表中,把開(kāi)始日期置為當(dāng)前日期,結(jié)束日期置為最大日期;
(6)將刪除數(shù)據(jù)和變化前數(shù)據(jù)插入歷史數(shù)據(jù)表中,把結(jié)束日期置為當(dāng)前日期。
方式一比較簡(jiǎn)潔;在數(shù)據(jù)量比較大的情況下,方式二效率比較高,因?yàn)橛脛h除插入的操作替代更新的操作,當(dāng)然,這是對(duì)于傳統(tǒng)數(shù)據(jù)庫(kù)而言,具體的方式應(yīng)根據(jù)實(shí)際數(shù)據(jù)量和數(shù)據(jù)庫(kù)來(lái)制定。
小結(jié)
本文用一個(gè)案例簡(jiǎn)單介紹了拉鏈表的含義以及實(shí)現(xiàn)拉鏈表的方式,如果有什么錯(cuò)誤,歡迎大家指正;如果對(duì)大家有幫助,希望大家能給個(gè)贊給予肯定支持,謝謝。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-478558.html
持續(xù)關(guān)注不迷路,轉(zhuǎn)載請(qǐng)注明出處:大數(shù)據(jù)的奇妙冒險(xiǎn)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-478558.html
到了這里,關(guān)于通俗易懂:什么是拉鏈表的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!