整取零存_欄位級遷移工具
阿新 • • 發佈:2020-07-07
> 6月份的大部分時間在完成一個特殊的資料遷移工具,將檔案中的標籤整合到關係型資料庫的表字段中。從近幾年的技術趨勢和參與的專案看,基本都是從關係型資料庫往大資料元件遷移。在這個專案中,主要是客戶和相關應用的供應商依賴於PostgreSQL的GIS外掛。因此我也有幸使用了一次PostgreSQL資料庫。本文簡要講解了工具開發的背景和難點,並給出了程式邏輯和原始碼連結。
# 01 需求和背景
**a). 為什麼說這是一個欄位級別的遷移?**
作為資料來源的標籤檔案數量非常多,根據標籤的分類和加工的便利程度,有大量含有各位資料標籤列的檔案。而同時在PG庫表中,為了減少join,提升資料庫查詢速度,大量標籤欄位又合在一張表中。結果就是存在,一個檔案的不同列可能對映到不同的表中,一張表的不同欄位來自於不同的檔案。檔案和表存在的是多對多的關係。這就造成不能簡單地做出某個檔案到某張表的對映關係,然後使用匯入工具匯入即可。
同時,對於客戶和使用者而言,他們希望看到的是就是標籤值(即對應資料庫中的欄位)。通過展示標籤級別的對映關係,終端使用者可以知曉每個標籤的業務含義和資料來源;通過展示每個標籤的加工狀態,管理員可以快速獲取整體標籤的可用性。
最後,資料來源結構上是半結構化的csv檔案,列的數量和存放順序可能發生改變。檔案和表的將是動態的,維護起來的工作量也過於巨大。
**b). 開發中依賴的一些業務說明**
首先,對於標籤類資料的存放表,認為是有業務主鍵的,這些主鍵也是其他應用查詢資料時的條件。程式中使用這些主鍵來完成新標籤資料的插入和舊標籤資料的更新。
對於明細類資料,資料來源的定義認為是沒有主鍵的日誌類資料,只有插入的操作無更新的操作。
同時,標籤的更新方式還分為增量和全量。增量即常規的merge操作,而全量方式需要將表中的指定標籤欄位置空後再進行merge操作。
# 02 遇到的問題和解決方法
**a). 檔案的匯入和併發控制**
雖然每一個任務都是欄位級別操作的,但是對於資料來源檔案的匯入存在多個標籤對應同一原始檔的情況,所以在檔案匯入操作上有一個專門的狀態表記錄檔案匯入的狀態。如果有其它標籤任務在執行相同的檔案匯入了,狀態就會變成`processing`。作為一個後來的任務,必須等待狀態為`success`或者`fail`時才能進行檔案的再次匯入。
同時為了避免檔案的再次匯入,每次匯入還會比較HDFS中檔案的時間戳和狀態表中的時間戳,如果時間戳一致,則直接使用已匯入的檔案即可。
**b). 檔案的動態入庫**
csv檔案的首行列名作為欄位名,檔名作為表明在臨時庫建立一張臨時表,然後使用`copy_expert`函式避免雙引號分界符內容中存在逗號的問題。
**c). 明細和標籤的整合**
為了讓兩者使用同一套欄位級別的merge方法,對於明細的資料在傳到本地檔案系統後,呼叫shell命令根據每一行的內容加行號md5 hash之後作為一行明細的主鍵。從而每一行資料都是唯一的,保證了資料在呼叫merge操作時只有insert行為。
**d). 派生欄位的處理**
這裡的派生欄位是指,在原檔案的列名中包含了一層資料,比如說同一個檔案存在一列名「甲品牌_銷售額」和「乙品牌_銷售額」,而最終的標籤需求為「銷售額」,「品牌」。即一列將變成兩列,同時資料行數將變成原有行數的(品牌列舉值個數)倍。
這個擴充套件的操作,是在原始檔入臨時庫之後,通過遍歷「品牌」列舉值,將其它列資料進行`union all`操作實現。
**e). 欄位型別轉換**
因為原始檔案匯入都是以文字形式入庫,實際標籤值可能有數字、布林、地理座標等型別,需要有一個專門的函式對標籤值進行型別轉換操作。
**f). PostgreSQL中的merge操作**
在PostgreSQL中,merge操作通過`insert into on conflict () do update set = excluded.`實現。
# 工具的處理邏輯
![etl_flow](https://img2020.cnblogs.com/blog/670593/202007/670593-20200706220100430-1216355170.png)
# 程式碼和遺留問題
程式碼github連結[github](https://github.com/camash/tag_level_etl)
**遺留問題:**
1. 對於主鍵的要求的強制的,但是程式沒有主動去目標表中增加主鍵;
2. 對於派生欄位只能提供增加一個欄位,不支援多個;
3. 在幾千條資料來源情況下,單個標籤匯入的時間為2秒左右,未對千萬級資料來源做效能測試;
4. 未提供多標籤同時匯入的介面
5. 執行資訊用了print()列印在螢幕,需要使用log模組優化輸出和分類。
# 總結
本文分享近期開發的一個標籤/欄位級別資料遷移的工具,通過Python實現。介紹了工具的一些背景和實現的一些難點。同時分享了工具的核心程式碼,拋磚引玉,希望跟有興趣的同學共同探討更高效的實現方式。
**歡迎掃描二維碼關注公眾號**
![](https://img2018.cnblogs.com/blog/670593/201912/670593-20191201214002980-30853