現代資料架構中,資料目錄的重要性日益凸顯。透過集中管理資料的元資料,資料目錄能有效提升資料的發現、理解和使用效率。本文將探討資料目錄的建置方法,並介紹如何利用 SQL 解析工具如 ANTLR 從資料函式庫中提取元資料,同時也將探討資料探索的概念及其在資料品質管理中的應用。從系統自動儲存的元資料到使用者自定義的物件標頭,我們需要思考如何利用這些資訊來評估資料的健康狀況和可用性。資料目錄的設計應該如同圖書館目錄,提供資料的位置、所有權和使用案例等資訊。自動化是建置資料目錄的關鍵,特別是對於擁有大量資料的大型資料倉儲。透過自動化工具,我們可以解析 SQL 陳述式,提取資料結構和關聯資訊,並將這些資訊儲存到資料目錄中。此外,資料探索的概念強調領域特定的動態理解和自動化資料發現,提供對資料狀態的即時理解,並協助回答與資料相關的重要問題。

資料品質與資料目錄的建立

在現代資料湖中,系統元資料(System Metadata)扮演著至關重要的角色。這些元資料通常包括:

  • 物件插入時間
  • 物件大小(以位元組為單位)
  • 物件檔案格式(如被識別)
  • 是否啟用加密

除了系統自動儲存的元資料外,您還可以在物件建立時指定額外的物件標頭(Object Headers)。這裡的資料品質解決方案更為開放,需要思考系統定義的元資料中缺少哪些資訊來評估資料停機時間(Data Downtime)。

一些例子包括:

  • 哪個作業流程或使用者負責此物件的建立?
  • 物件使用或依賴的結構是什麼?例如,您可以對上游轉換的結構進行雜湊處理,以判斷該資源是否組態為特定的ETL工作流程,或者其中一側的轉換是否已被棄用。

然而,請記住,另一個常見(也許更全面)的方法來回答「誰負責此物件的建立?」這個問題是實施更嚴格的存取許可權控制,並且只授予單一流程寫入許可權。雖然這是一種雄心壯志的方法,但它確保資料品質得到更主動的處理。

資料目錄的設計

與實體圖書館目錄類別似,資料目錄(Data Catalog)作為元資料的清單,為投資者提供評估資料可存取性、健康狀況和位置所需的資訊。Alation、Collibra和Informatica等公司提供的解決方案不僅可以跟蹤您的資料,還可以與機器學習和自動化整合,使資料更易於發現、協作,並且現在還可以符合組織、行業或甚至政府法規的要求。

由於資料目錄提供了公司資料來源的單一真實來源,因此很容易利用資料目錄來管理管道中的資料。資料目錄可用於儲存元資料,讓利益相關者更好地瞭解特定來源的沿襲(Lineage),從而增加對資料本身的信任。此外,資料目錄使得跟蹤個人可識別資訊(Personally Identifiable Information, PII)在管道中的存放和擴散,以及組織中誰有權存取這些資訊變得更加容易。

資料目錄旨在回答以下問題:

  • 我應該在哪裡尋找我的資料?
  • 這些資料重要嗎?
  • 這些資料代表什麼?
  • 這些資料是否相關且重要?
  • 我如何使用這些資料?

如果您是公司中第一個設計資料目錄的人,那麼最簡單的方法是將所有資料資訊彙總到一個巨大的試算表中。傳統上,這就是資料目錄的建立方式——使用Excel。

然而,手動建立資料目錄的問題很容易被識別出來。對於擁有數萬個表格的大型資料倉儲,自動化的需求是不可避免的。傳統的資料目錄和治理方法通常依賴資料團隊進行繁重的手動資料輸入工作,要求他們在資料資產演變時更新目錄。這種方法不僅耗時,而且需要大量的手動工作,這些工作本來可以被自動化,從而讓資料工程師和分析師騰出時間專注於真正推動進展的專案。

此外,今天儲存的大部分資料都是非結構化和高度流動的——這種資料非常適合被納入機器學習管道,並且通常儲存在資料湖中。對於這些形式的資料,維護手動目錄簡直是不可能的,除非您願意讓少數工程師全職負責這項任務。此外,不僅需要描述資料消費者存取和使用的資料,還需要根據資料的意圖和目的來理解資料。資料生產者對資料資產的描述與資料消費者對其功能的理解可能大不相同,甚至不同的資料消費者之間對資料含義的理解也可能存在巨大差異。總而言之,手動資料目錄已經不能滿足需求了。

幸運的是,資料目錄的建立可以透過發現和組織適當的元資料來實作自動化。我們已經確定這是可以自動化的。

建立資料目錄

假設您想從頭開始建立資料目錄(願原力與您同在!)——您該如何開始?

在建立或投資資料目錄之前,您需要與下游利益相關者和分析團隊合作,瞭解哪些資料對業務最重要,因此需要被記錄和編目。許多團隊透過使用試算表來突出資料來源、其連線的內容以及最後更新時間來完成第一步(對齊)。

完成對齊後,團隊應該指派負責人負責保持他們的欄位(和資料!)更新。一些團隊根據來源、結構或甚至資料領域來分配所有權。

在其最基本的層面,資料目錄是關於您資料的元資料集合,它提供了資料的位置、所有權和潛在使用案例的背景和洞察力。為了實際填充資料目錄,如其最基本狀態所示(表2-1),資料團隊可以手動檢查資料倉儲中的每個表格,或者使用自動化的SQL解析器來完成這項工作。Sqlparse、ANTLR、Apache Calcite和MySQL的SQL Parser都是流行的開源SQL解析解決方案。

表2-1 一個基本、粗糙的資料目錄範例

表名儀錶板/報告最後更新所有者註解
LIOR_GOOD_TABLE_3.csvExec Forecasting V3 (Looker)2022年3月3日Lior Gavish (lior@internet.org)Lior的表格;用於執行財務預測,即ARR
MEETINGS_DOWNTIME_2022.csvReport1234 (Tableau)2022年2月2日Barr Moses (barr@internet.org)會議期間發生的中斷
DONT_USE_4_MV.csvDashboard Yikes (Chartio)2021年10月30日Molly Vorwerck (molly@internet.org)誰知道呢?
RYANS_DATA.csvMarketing Model (Looker)2022年3月3日Ryan Kearns (ryan@internet.org)用於需求生成模型,以通知跨社交通路的廣告支出

SQL解析器將SQL陳述式的各個部分(即關鍵字、識別碼、子句等)分離到其他例程可以處理的資料結構中。

一旦您解析了SQL,您就需要一個地方來儲存和處理它。開源資料函式庫如開源ELK堆積疊、PostgreSQL、MySQL和MariaDB都是從頭建立資料目錄時的絕佳選擇。

-- SQL 解析範例
SELECT * FROM users WHERE age > 18;

內容解密:

上述SQL查詢陳述式用於從名為users的資料表中選取所有年齡大於18歲的使用者資料。首先,SELECT *表示選取所有欄位,FROM users指定了資料表名稱,WHERE age > 18則是篩選條件,確保只傳回符合條件的資料列。

# 使用sqlparse解析SQL陳述式的範例
import sqlparse

sql = "SELECT * FROM users WHERE age > 18;"
parsed = sqlparse.parse(sql)

for token in parsed[0].tokens:
    print(token.ttype, token.value)

內容解密:

這段Python程式碼使用了sqlparse函式庫來解析SQL陳述式。首先匯入sqlparse函式庫,然後定義了一個SQL查詢字串。透過sqlparse.parse(sql)解析SQL陳述式,並將結果儲存在parsed變數中。最後,遍歷解析後的SQL陳述式中的每個標記(token),並列印出其型別和值。

  graph LR;
    A[開始] --> B{解析SQL陳述式};
    B -->|成功| C[儲存解析結果];
    B -->|失敗| D[錯誤處理];
    C --> E[進一步分析或執行];
    D --> F[記錄錯誤];

圖表翻譯: 此圖表展示了SQL陳述式解析流程。首先,流程從「開始」開始,然後進入「解析SQL陳述式」的判斷階段。如果解析成功,則進入「儲存解析結果」步驟;如果解析失敗,則進入「錯誤處理」步驟。成功解析後,可以進一步進行分析或執行SQL陳述式;失敗時,則進行錯誤記錄。

資料目錄建置與資料探索的重要性

在現代資料架構中,資料目錄(Data Catalog)扮演著至關重要的角色。資料目錄是一種集中式的倉函式庫,用於儲存和管理資料的中繼資料(Metadata),使得資料能夠被有效地發現、理解和使用。本章節將探討資料目錄的建置、資料探索的概念,以及它們如何協助組織實作可靠的資料系統。

使用ANTLR進行SQL解析

為了從資料函式庫中提取中繼資料,我們可以使用ANTLR(Another Tool for Language Recognition)來解析SQL查詢。ANTLR是一種強大的解析器生成器,可以根據語法規格生成解析器。以下是一個使用ANTLR解析MySQL查詢的範例程式碼:

String sql = "SELECT CUST_NAME FROM CUSTOMERS WHERE CUST_NAME LIKE 'Kash%'";
MySqlLexer lexer = new MySqlLexer(CharStreams.fromString(sql));
MySqlParser parser = new MySqlParser(new CommonTokenStream(lexer));
ParseTree root = parser.dmlStatement();
System.out.println(root.toStringTree(parser));

內容解密:

  1. 首先,我們定義了一個SQL查詢字串,查詢客戶名稱以"Kash"開頭的客戶。
  2. 使用MySqlLexer對SQL查詢進行詞法分析,將查詢字串分解為詞法單元(Tokens)。
  3. 然後,使用MySqlParser對詞法單元進行語法分析,生成解析樹(Parse Tree)。
  4. 最後,列印預出解析樹的字串表示形式,展示了查詢的語法結構。

資料目錄的輸出結果

上述查詢的輸出結果是一個解析樹,展示了查詢的語法結構,如下所示:

(dmlStatement
  (selectStatement
    (querySpecification SELECT
      (selectElements
        (selectElement
          (fullColumnName
            (uid
              (simpleId CUST_NAME)))))
      (fromClause FROM
        (tableSources
          (tableSource
            (tableSourceItem
              (tableName
                (fullId
                  (uid
                    (simpleId CUSTOMERS))))))) WHERE (expression (predicate
                      (predicate
                        (expressionAtom
                          (fullColumnName
                            (uid (simpleId CUST_NAME))))) LIKE
                      (predicate
                        (expressionAtom
                          (constant
                            (stringLiteral 'Kash%'))))))))))

內容解密:

  1. 解析樹展示了查詢的語法結構,包括SELECT陳述式、FROM子句和WHERE子句。
  2. 每個節點代表查詢中的一個元素,例如列名稱、表名稱和條件表示式。
  3. 透過解析樹,我們可以提取查詢的中繼資料,例如查詢的目標列和表。

開源查詢語言工具的應用

開源查詢語言工具如GraphQL、REST和Cube.js可以與SQL資料函式庫互動,並將查詢結果渲染到資料目錄視覺化服務中,例如Amundsen、Apache Atlas、DataHub或CKAN。這些工具使得資料探索和資料目錄建置變得更加容易和靈活。

資料探索的概念

資料探索(Data Discovery)是一種新的方法,用於理解分散式資料資產的健康狀態和當前狀態。資料探索借鑒了Zhamak Dehghani提出的分散式領域導向架構(Domain-Oriented Architecture)和Thoughtworks的資料網格模型(Data Mesh Model)。資料探索強調不同資料所有者對其資料的負責,以及促進不同地點之間的資料溝通。

資料探索的特點

資料探索具有以下特點:

  • 領域特定的動態理解:資料探索根據資料的擷取、儲存、聚合和使用方式,提供領域特定的動態理解。
  • 自動化資料發現:資料探索支援自動化資料發現和活動中繼資料。
  • 即時理解:資料探索提供即時理解資料的當前狀態,而不是理想狀態或“目錄”狀態。

資料探索的應用

資料探索可以回答以下問題:

  • 哪個資料集是最新的?哪些資料集可以被棄用?
  • 上次更新這個表格是什麼時候?
  • 在我的領域中,某個欄位的含義是什麼?
  • 誰有權存取這個資料?上次使用是什麼時候?由誰使用?
  • 這個資料的上游和下游依賴關係是什麼?
  • 這是生產級別的資料嗎?
  • 哪些資料對於我的領域的業務需求是重要的?
  • 我對這個資料的假設是否正確?

資料目錄的未來發展

未來的資料目錄將具備學習、理解和推斷資料的能力,讓使用者能夠以自助服務的方式利用資料的洞察力。資料目錄將支援自動化資料發現和活動中繼資料,使得資料探索和資料目錄建置變得更加智慧和高效。

資料目錄的關鍵特性

自助服務探索和自動化

資料團隊應該能夠輕鬆地利用資料目錄,而無需專門的支援團隊。自助服務、自動化和工作流程協調使得資料工具之間的隔閡被消除,從而使得資料更容易被理解和存取。更高的可存取性自然會導致資料採用率的提高,從而減少資料工程團隊的負擔。

資料演進中的可擴充套件性

隨著公司攝入越來越多的資料和非結構化資料成為常態,能夠擴充套件以滿足這些需求的能力對於資料計劃的成功至關重要。資料探索利用機器學習來獲得對資料資產的鳥瞰圖,從而確保對資料的理解能夠隨著資料的演進而適應。這樣,資料消費者就能夠做出更明智和有根據的決定,而不是依賴過時的檔案(即關於資料的資料,它會變得過時,這是很諷刺的!)或更糟糕的——根據直覺的決策。

分散式探索的資料血統

資料探索在很大程度上依賴於自動化的表和欄位級別的血統來對映資料資產之間的上下游依賴關係。血統有助於在正確的時間提供正確的資訊(資料探索的核心功能),並在資料資產之間建立聯絡,以便在資料管道斷裂時更好地進行故障排除。隨著現代資料堆積疊的發展以適應更複雜的使用場景,這個問題正變得越來越普遍。在第7章中,我們將探討如何為自己的資料管道建立血統。

資料收集、清理、轉換與測試

在瞭解了優先考慮資料可靠性的各種必要工具後,我們來討論如何準備資料以供生產使用,同時兼顧資料品質。

資料收集

資料收集是資料管道中最重要的環節之一。我們將資料進入管道的初始接觸點稱為「入口點」(entrypoint)。入口點的資料是最原始的,因為它包含了外界的所有雜訊和不規則性。這些資料可能來自應用程式或服務日誌、點選流來源或即時感測器。我們的資料可能高度異質化,即同時包含結構化和非結構化資料,這為下游處理帶來了挑戰。

資料來源通常不是由資料工程師決定的,而是取決於某些業務目標或上游工具,如分析服務或API。資料來源大致可分為三類別:

應用程式日誌資料

應用程式日誌是指由軟體應用程式內部動作產生的資料。這些動作可以是使用者發起的,也可以是程式發起的。除了事件描述外,日誌中可能還包含錯誤或警告訊息。與系統日誌不同,應用程式日誌的內容取決於應用程式開發人員的設計,因此可能不代表應用程式使用的完整歷史。

以下是一些應用程式日誌資料的例子:

  • 一位使用者在網頁上花了10分鐘,點選了三個外部連結,並滾動到檔案底部。
  • 一位工程師在雲端運算服務上建立了一個虛擬機器例項,但選擇的例項型別在該地區不可用,因此需要修改組態。
  • 一個機器學習模型正在擬合資料集。日誌記錄了不同的訓練週期、目前的準確度以及外部儀錶板的連結。

處理應用程式日誌資料時需要考慮以下幾個方面:

  • 結構:應用程式日誌通常以ASCII或二進位格式儲存,結構可變,長度不固定。
  • 時間戳:大多數應用程式日誌事件都帶有時間戳,通常採用ISO標準格式(yyyy-mm-ddThh:mm:ss[.mmm])。
  • 日誌級別:良好的應用程式日誌使用級別來表示事件的型別,例如INFO、WARN和ERROR。
  • 用途:應用程式日誌通常用於診斷或稽核目的。診斷日誌關注特定的錯誤或警告,而稽核日誌則記錄應用程式的事件歷史。

API 回應

應用程式通常需要依賴其他應用程式來完成某些功能,這是透過應用程式介面(API)實作的。API是兩個程式之間的媒介,需要特定格式的請求,並傳回半結構化的資料。

資料清理

內容解密:

在處理應用程式日誌資料時,我們需要了解其結構和內容。應用程式日誌可能包含多種格式和結構,這使得資料清理變得非常重要。我們需要從日誌中提取有用的資訊,例如時間戳、事件描述和錯誤訊息等。同時,我們也需要處理日誌中的雜訊和不規則性,以確保資料的品質。

程式碼範例:

import re
from datetime import datetime

# 假設我們有一個應用程式日誌檔案
log_data = [
    "2023-03-01T12:00:00 INFO User logged in",
    "2023-03-01T12:00:01 WARN Invalid input",
    "2023-03-01T12:00:02 ERROR Database connection failed"
]

# 定義一個函式來解析日誌資料
def parse_log_data(log_data):
    parsed_data = []
    for log in log_data:
        # 使用正規表示式提取時間戳、日誌級別和事件描述
        timestamp = re.search(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}', log).group()
        log_level = re.search(r'INFO|WARN|ERROR', log).group()
        event_description = re.search(r'INFO|WARN|ERROR (.*)', log).group(1)
        
        # 將時間戳轉換為datetime物件
        timestamp = datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S')
        
        # 將解析後的資料儲存在字典中
        parsed_data.append({
            'timestamp': timestamp,
            'log_level': log_level,
            'event_description': event_description
        })
    
    return parsed_data

# 解析日誌資料
parsed_log_data = parse_log_data(log_data)

# 列印解析後的資料
for log in parsed_log_data:
    print(log)

內容解密:

在這個程式碼範例中,我們定義了一個函式parse_log_data來解析應用程式日誌資料。我們使用正規表示式提取時間戳、日誌級別和事件描述,並將時間戳轉換為datetime物件。最後,我們將解析後的資料儲存在字典中並傳回。

這個範例展示瞭如何從應用程式日誌中提取有用的資訊,並將其轉換為結構化的資料,以便於進一步的分析和處理。

圖表說明

此圖示展示了應用程式日誌資料的處理流程:

  graph LR
    A[原始日誌資料] --> B[解析日誌資料]
    B --> C[提取時間戳]
    B --> D[提取日誌級別]
    B --> E[提取事件描述]
    C --> F[轉換時間戳格式]
    D --> G[分類別日誌級別]
    E --> H[儲存事件描述]
    F --> I[儲存解析後的資料]
    G --> I
    H --> I

圖表翻譯:

這個圖表展示了應用程式日誌資料的處理流程。首先,我們從原始日誌資料開始,然後解析日誌資料。解析過程中,我們提取時間戳、日誌級別和事件描述。提取的時間戳會被轉換為標準格式,日誌級別會被分類別,事件描述會被儲存。最後,所有解析後的資料都會被儲存起來,以便於進一步的分析和處理。