戰(zhàn):從 JSONL 查詢?nèi)罩窘馕鲅壟c操作元數(shù)據(jù))
DataHub SQL Queries 采集源實(shí)戰(zhàn)從 JSONL 查詢?nèi)罩窘馕鲅壟c操作元數(shù)據(jù)【免費(fèi)下載鏈接】datahubThe Context Platform for your Data and AI Stack項(xiàng)目地址: https://gitcode.com/GitHub_Trending/da/datahubsql-queries是 DataHub 元數(shù)據(jù)采集框架metadata-ingestion中用于生產(chǎn)環(huán)境血緣攝取的核心模塊它讀取一個(gè)換行分隔的 JSONJSONL文件中記錄的 SQL 查詢通過 SQL 解析引擎自動生成表級與字段級血緣Lineage并可進(jìn)一步產(chǎn)出查詢實(shí)體Query、使用統(tǒng)計(jì)與操作事件Operation。本文以倉庫中的 sql-queries_pre.md 文檔為主線結(jié)合 sql_queries.py 源碼與 集成測試用例 的輸入樣例完整講解該采集源的輸入格式、配置項(xiàng)、運(yùn)行方式與底層實(shí)現(xiàn)原理。讀完本文你將能夠把任意平臺導(dǎo)出的 SQL 查詢?nèi)罩颈镜匚募?S3 對象轉(zhuǎn)化為 DataHub 中可檢索、可追溯的血緣與操作元數(shù)據(jù)。模塊定位與核心能力根據(jù) sql-queries_pre.md 的說明sql-queries模塊的職責(zé)是從 SQL 查詢中攝取元數(shù)據(jù)到 DataHub它面向生產(chǎn)級攝取工作流production ingestion workflows模塊特有的能力在文檔中單獨(dú)說明。從源碼實(shí)現(xiàn)看該模塊在 DataHub 的 source 注冊表中以sql-queries為平臺 id 注冊并聲明了三項(xiàng)能力見 sql_queries.py 的裝飾器聲明能力支持狀態(tài)說明LINEAGE_COARSE粗粒度血緣支持從 SQL 解析出的表級上下游關(guān)系LINEAGE_FINE細(xì)粒度血緣支持從 SQL 解析出的字段級血緣OPERATION_CAPTURE操作捕獲支持從非 SELECT 查詢INSERT/UPDATE/CREATE 等解析出操作事件該 source 在框架中的支持狀態(tài)為GAGeneral Availability正式可用。它的工作方式非常直接讀取一個(gè)包含 SQL 查詢的換行分隔 JSON 文件解析這些查詢以生成血緣。與 Snowflake、BigQuery 等直接連接數(shù)據(jù)源采集 usage 的 source 不同sql-queries不直接連接任何數(shù)據(jù)庫而是消費(fèi)已經(jīng)導(dǎo)出的查詢?nèi)罩疽虼怂绕溥m合離線血緣回填、無法直連數(shù)據(jù)庫的環(huán)境以及多平臺查詢?nèi)罩窘y(tǒng)一入湖等場景。前置條件官方文檔在 Prerequisites 一節(jié) 明確了運(yùn)行前的三項(xiàng)前置要求網(wǎng)絡(luò)連通性確保采集環(huán)境能訪問查詢?nèi)罩舅谖恢帽镜匚募到y(tǒng)或 S3以及 DataHub GMS有效的認(rèn)證憑據(jù)配置可用的 DataHub 訪問憑據(jù)datahub_api下的 token 或用戶名密碼元數(shù)據(jù) API 的讀權(quán)限該模塊需要讀取 DataHub 中已存在的 SchemaMetadata表結(jié)構(gòu)等元數(shù)據(jù)來輔助 SQL 解析。源碼進(jìn)一步印證了這一點(diǎn)SqlQueriesSource.__init__在構(gòu)造時(shí)會強(qiáng)制校驗(yàn)ctx.graph即 DataHub API 客戶端非空否則直接拋出ValueError(SqlQueriesSource needs a datahub_api from which to pull schema metadata)見 sql_queries.py#L183-L187。也就是說該采集源必須在配置了datahub_api的前提下運(yùn)行它依賴 DataHub 作為 schema 解析的知識來源。輸入格式JSONL 查詢文件詳解sql-queries的輸入是一個(gè)換行分隔的 JSON 文件NDJSON/JSONL每一行是一個(gè) JSON 對象對應(yīng)一條查詢記錄。每行的字段由源碼中的QueryEntry模型定義見 sql_queries.py#L471-L477字段類型必填說明querystr是SQL 查詢文本血緣與操作解析的核心輸入timestampdatetime可空否查詢執(zhí)行時(shí)間支持 Unix 秒級時(shí)間戳或任意可被parse_user_datetime解析的日期格式userCorpUserUrn可空否執(zhí)行查詢的用戶可為 DataHub corpuser URN 字符串空字符串會被視為無執(zhí)行者而不會導(dǎo)致該行失敗downstream_tablesList[DatasetUrn]否顯式血緣中的下游表列表upstream_tablesList[DatasetUrn]否顯式血緣中的上游表列表session_idstr可空否會話標(biāo)識用于跨查詢維護(hù)臨時(shí)表映射倉庫中的 basic.jsonl 給出了最典型的三字段輸入樣例{query: SELECT * FROM snowflake.db.users, timestamp: 1609459200, user: john.doe} {query: INSERT INTO snowflake.db.orders SELECT user_id, product_id, order_date FROM snowflake.db.temp_orders, timestamp: 1609459260, user: jane.smith} {query: CREATE VIEW snowflake.db.user_summary AS SELECT u.id, u.name, COUNT(o.id) as order_count FROM snowflake.db.users u LEFT JOIN snowflake.db.orders o ON u.id o.user_id GROUP BY u.id, u.name, timestamp: 1609459320, user: admin} {query: UPDATE snowflake.db.users SET last_login CURRENT_TIMESTAMP WHERE id IN (SELECT DISTINCT user_id FROM snowflake.db.sessions WHERE session_date 2021-01-01), timestamp: 1609459380, user: system}從上面的樣例可以看到sql-queries能處理SELECT、INSERT ... SELECT、CREATE VIEW、UPDATE、CREATE TABLE AS等多種語句形態(tài)它們分別對應(yīng)血緣、查詢實(shí)體、操作事件等不同產(chǎn)出的解析路徑。逐行容錯(cuò)解析源碼中_parse_lines的實(shí)現(xiàn)見 sql_queries.py#L365-L403體現(xiàn)了面向生產(chǎn)設(shè)計(jì)的容錯(cuò)策略空行自動跳過每一行獨(dú)立使用json.loads(line, strictFalse)解析單行格式錯(cuò)誤不會中斷整個(gè)攝取而是計(jì)入num_entries_failed并記錄 warning 后繼續(xù)每處理 1000 行輸出一次進(jìn)度日志方便觀察長文件的處理節(jié)奏若所有行都解析失敗_report_run_health會將其上報(bào)為failure而非常規(guī) warning使流水線以非零退出碼結(jié)束避免看似成功實(shí)則空跑的假綠見 sql_queries.py#L269-L299。顯式血緣Explicit Lineage輸入除了讓解析器從 SQL 文本中自動推斷血緣輸入行還支持通過upstream_tables/downstream_tables直接聲明血緣關(guān)系。倉庫中的 explicit-lineage.jsonl 展示了這種用法{query: INSERT INTO snowflake.db.orders SELECT user_id, product_id, order_date FROM snowflake.db.temp_orders, timestamp: 1609459260, user: jane.smith, upstream_tables: [snowflake.db.users], downstream_tables: [snowflake.db.audit_log]}源碼中的處理邏輯見 sql_queries.py#L418-L453如下若某行同時(shí)提供upstream_tables和downstream_tables則走KnownQueryLineageInfo路徑完全信任文件中的顯式血緣不再對該行做 SQL 解析若只提供了其中一側(cè)如只有上游沒有下游則記錄日志說明部分血緣缺失回退到 SQL 解析并按普通查詢交給解析聚合器處理表名字符串會被轉(zhuǎn)換為make_dataset_urn_with_platform_instance生成的 Dataset URN因此表名會遵循配置中的platform、platform_instance與envupstream_tables/downstream_tables必須是列表傳入裸字符串會直接報(bào)錯(cuò)源碼特意注釋了這一點(diǎn)防止字符串被逐字符拆開偽造出血緣列表中的非法條目會被忽略并計(jì)入num_invalid_table_entries同時(shí)給出 warning。配置項(xiàng)全解SqlQueriesSourceConfig見 sql_queries.py#L75-L148繼承自PlatformInstanceConfigMixin、EnvConfigMixin和IncrementalLineageConfigMixin即它同時(shí)支持 DataHub 通用的platform_instance平臺實(shí)例、env環(huán)境默認(rèn) PROD以及增量血緣相關(guān)配置。模塊自身的配置項(xiàng)如下配置項(xiàng)類型默認(rèn)值說明query_filestr必填待攝取的查詢文件路徑支持本地路徑與s3://URIplatformstr必填生成元數(shù)據(jù)時(shí)使用的平臺標(biāo)識例如snowflake、bigquery該值決定 Dataset URN 中的 platform 部分usageBaseUsageConfig默認(rèn)實(shí)例生成使用統(tǒng)計(jì)時(shí)的配置如start_time、end_time、bucket_durationuse_schema_resolverbooltrue是否從 DataHub 讀取 SchemaMetadata 輔助 SQL 解析僅測試時(shí)可關(guān)閉default_dbstrNone未限定庫名的表默認(rèn)歸屬的數(shù)據(jù)庫default_schemastrNone未限定 schema 名的表默認(rèn)歸屬的 schemaoverride_dialectstrNone強(qiáng)制指定 SQL 方言覆蓋自動方言檢測temp_table_patternsList[str][]臨時(shí)表正則模式列表用于在血緣攝取中過濾臨時(shí)表aws_configAwsConnectionConfigNoneS3 訪問配置當(dāng)query_file為s3://URI 時(shí)必填關(guān)鍵配置項(xiàng)說明query_file與 S3 支持。query_file既可以是本地文件也可以是 S3 對象 URI。源碼通過is_s3_uri判斷并在模型校驗(yàn)器validate_s3_config中強(qiáng)制要求當(dāng)query_file以s3://開頭時(shí)必須同時(shí)提供aws_config否則配置階段直接報(bào)錯(cuò)見 sql_queries.py#L136-L142。讀取 S3 文件時(shí)使用smart_open配合aws_config.get_s3_client()建立流式讀取見 sql_queries.py#L301-L322因此即便查詢文件很大也能以流式逐行處理內(nèi)存占用可控。temp_table_patterns臨時(shí)表過濾。這是血緣質(zhì)量的關(guān)鍵配置。某些平臺如 Athena沒有原生臨時(shí)表概念但會用命名約定來模擬臨時(shí)表例如temp_前綴、_temp后綴。若不加以過濾這些中間表會大量污染血緣圖。源碼規(guī)定模式使用起始錨定匹配re.match與AllowDenyPattern一致例如temp_能匹配任何以temp_開頭的表編譯時(shí)統(tǒng)一忽略大小寫re.IGNORECASE模式本身會在配置校驗(yàn)階段被re.compile驗(yàn)證非法正則直接報(bào)錯(cuò)見 sql_queries.py#L124-L134命中臨時(shí)表模式時(shí)is_temp_table回調(diào)會返回 True 并計(jì)入num_temp_table_matches解析聚合器據(jù)此在血緣圖中濾除這些表見 sql_queries.py#L455-L468。倉庫測試 temp-table-patterns.yml 中的用法示例temp_table_patterns: [^temp_.*, ^tmp_.*, .*_temp$]use_schema_resolverSchema 解析器。開啟后默認(rèn)開啟source 會構(gòu)造SchemaResolver從 DataHub 拉取已注冊表的 SchemaMetadata 作為 SQL 解析的上下文。由于真實(shí)世界的 SQL 往往使用未限定的表名、別名、大小寫變體擁有列級 schema 信息能顯著提升解析準(zhǔn)確率。該配置在源碼中被標(biāo)記為HiddenFromDocs屬于面向測試的開關(guān)生產(chǎn)環(huán)境建議保持默認(rèn)開啟。default_db/default_schema。當(dāng)查詢?nèi)罩局械谋砻磶烀?schema 限定時(shí)這兩個(gè)配置提供兜底的解析上下文。例如查詢只寫了SELECT * FROM orders配合default_db: snowflake、default_schema: db可解析為snowflake.db.orders。override_dialect。sql-queries底層使用 SQLGlot 解析引擎通常會自動檢測方言但當(dāng)自動檢測在混合方言日志中表現(xiàn)不穩(wěn)定時(shí)可通過該配置顯式指定方言如snowflake、bigquery、spark。usage使用統(tǒng)計(jì)配置。通過嵌套的BaseUsageConfig控制使用統(tǒng)計(jì)的生成窗口與聚合粒度。倉庫測試 basic.yml 中的典型配置usage: start_time: 2021-01-01T00:00:00Z end_time: 2021-01-02T00:00:00Z bucket_duration: DAY已移除的配置項(xiàng)源碼通過pydantic_removed_field標(biāo)記了enable_lazy_schema_loading這一歷史配置它已在2026 年 8 月被正式移除見 sql_queries.py#L120-L122。如果你在舊版 recipe 中看到該配置升級后應(yīng)直接刪除否則會收到配置校驗(yàn)告警。完整的 Recipe 示例以下 recipe 來自倉庫集成測試 basic.yml展示了一個(gè)可運(yùn)行的完整配置骨架source: type: sql-queries config: query_file: ./input/basic.jsonl platform: snowflake use_schema_resolver: false usage: start_time: 2021-01-01T00:00:00Z end_time: 2021-01-02T00:00:00Z bucket_duration: DAY sink: type: file config: filename: ./output.json datahub_api: server: http://localhost:8080實(shí)際生產(chǎn)環(huán)境中一般建議將use_schema_resolver保持為true默認(rèn)并正確配置datahub_api.server指向 DataHub GMS若查詢?nèi)罩颈砻赐耆薅ㄑa(bǔ)充default_db與default_schema若平臺存在臨時(shí)表命名約定配置temp_table_patterns過濾中間表查詢文件存放在 S3 時(shí)補(bǔ)充aws_configregion、憑據(jù)等并將query_file寫為s3://bucket/path/queries.jsonl。運(yùn)行命令為標(biāo)準(zhǔn)的 DataHub ingestion CLIdatahub ingest -c recipe.yml底層實(shí)現(xiàn)原理解析聚合器與 Schema 解析sql-queries的核心設(shè)計(jì)是解析與產(chǎn)出分離攝取階段把每條查詢喂給SqlParsingAggregator產(chǎn)出階段再由聚合器統(tǒng)一生成各類元數(shù)據(jù)工作單元workunit。兩階段攝取流程get_workunits_internal見 sql_queries.py#L242-L267將一次運(yùn)行劃分為兩個(gè)報(bào)告階段QUERIES_EXTRACTION查詢抽取逐行讀取查詢文件把每條查詢加入聚合器。單條查詢加入失敗如解析異常不會中止運(yùn)行而是計(jì)入num_queries_aggregator_failures并記錄 warning但系統(tǒng)性錯(cuò)誤內(nèi)存溢出、進(jìn)程中斷、網(wǎng)絡(luò)認(rèn)證類異常會被重新拋出以終止任務(wù)LINEAGE_EXTRACTION血緣抽取調(diào)用aggregator.gen_metadata()生成所有血緣、查詢、使用統(tǒng)計(jì)與操作元數(shù)據(jù)并通過auto_workunit包裝為統(tǒng)一的工作單元流輸出。SqlParsingAggregator 的初始化參數(shù)聚合器的構(gòu)造見 sql_queries.py#L207-L225揭示了模塊的能力開關(guān)這些參數(shù)當(dāng)前在源碼中標(biāo)記為 TODO 待配置化但已經(jīng)全部啟用參數(shù)值作用generate_lineagetrue生成血緣generate_queriestrue生成 Query 實(shí)體generate_query_subject_fieldstrue生成查詢主題字段generate_query_usage_statisticstrue發(fā)布 SELECT 查詢實(shí)體僅當(dāng)開啟時(shí)才會為 SELECT 發(fā)布 Query 實(shí)體否則只發(fā)布寫操作類查詢generate_usage_statisticstrue生成使用統(tǒng)計(jì)generate_operationstrue生成操作事件從非 SELECT 查詢解析eager_graph_loadfalse不從 DataHub 預(yù)加載全量 schema按需惰性加載is_temp_table配置了temp_table_patterns時(shí)為回調(diào)臨時(shí)表判定回調(diào)format_queriesfalse是否格式化查詢文本會話與臨時(shí)表追蹤源碼實(shí)現(xiàn)注釋明確指出模塊通過session_id跨查詢維護(hù)臨時(shí)表映射同一會話中CREATE TEMP TABLE之后的查詢引用該臨時(shí)表時(shí)解析器能正確追蹤其真實(shí)上游。這一能力由集成測試 session-temp-tables.jsonl 對應(yīng)的session-temp-tables用例驗(yàn)證其 golden 文件位于 session-temp-tables.json。增量血緣與補(bǔ)丁格式由于配置類繼承了IncrementalLineageConfigMixin該 source 還支持增量血緣每次運(yùn)行可以只處理新增的查詢窗口避免全量重算。同時(shí)測試目錄中的patch-lineage用例表明血緣可以采用patch 格式MCP Patch輸出而非全量覆蓋式的 upstreamLineage這為頻繁增量攝取提供了更低開銷的更新方式。測試驗(yàn)證與產(chǎn)出樣例倉庫在 tests/integration/sql_queries 目錄下提供了完整的集成測試套件覆蓋了該模塊的九類典型場景可直接作為理解模塊行為的活文檔測試用例驗(yàn)證點(diǎn)basic基礎(chǔ)血緣解析SELECT/INSERT/CREATE VIEW/UPDATE/CTAS 混合場景basic-with-schema-resolver開啟 Schema Resolver 后的解析差異session-temp-tables同一 session 內(nèi)臨時(shí)表血緣的正確追蹤query-deduplication重復(fù)查詢的去重explicit-lineage文件內(nèi)顯式聲明血緣的信任路徑hex-origin十六進(jìn)制 origin 相關(guān)場景patch-lineage血緣以 patch 格式輸出lazy-schema-resolver惰性 schema 加載temp-table-patterns臨時(shí)表正則過濾對血緣圖的凈化效果測試運(yùn)行方式見 test_sql_queries.py值得注意它通過 docker-compose 啟動一個(gè)MockServer 模擬 DataHub將datahub_api.server指向臨時(shí)端口通過環(huán)境變量SQL_QUERIES_MOCK_PORT注入隨后用Pipeline.create(recipe)真實(shí)執(zhí)行攝取最后將輸出與 golden 文件比對。這說明該模塊的端到端鏈路讀文件 → 解析 → 聚合 → 產(chǎn)出 → 上報(bào)完全可以在無真實(shí) DataHub 實(shí)例的情況下被驗(yàn)證。各用例的輸入文件.jsonl.ymlrecipe與期望輸出golden/*.json一一對應(yīng)例如 basic.jsonl 的期望血緣輸出見 basic.json適合讀者對照學(xué)習(xí)每類 SQL 語句最終會生成哪些 MCP 元數(shù)據(jù)。運(yùn)行狀態(tài)與排障SqlQueriesSourceReport見 sql_queries.py#L151-L161提供了完善的運(yùn)行觀測指標(biāo)運(yùn)行結(jié)束后可通過datahub ingest的輸出或報(bào)告 API 查看指標(biāo)含義num_entries_processed成功解析的輸入行數(shù)num_entries_failed解析失敗被跳過的行數(shù)單行壞數(shù)據(jù)不影響整體num_queries_processed成功加入解析聚合器的查詢數(shù)num_queries_aggregator_failures加入聚合器失敗的查詢數(shù)num_invalid_table_entries顯式血緣中被忽略的非法表引用數(shù)num_temp_table_matches命中臨時(shí)表模式被過濾的表數(shù)sql_aggregator/schema_resolver_report聚合器與 schema 解析器的子報(bào)告排障時(shí)可關(guān)注以下已知邊界行為所有行解析失敗報(bào)告會以 failure 級別提示check the file format (expected newline-delimited JSON)通常意味著文件并非 JSONL 格式或編碼異常所有查詢聚合失敗報(bào)告會提示可能是認(rèn)證、連通性、配置等系統(tǒng)性問題的信號空輸入文件存在但沒有查詢條目時(shí)會給出 warning 而非 failure空字符串 user很多平臺導(dǎo)出的查詢?nèi)罩緯严到y(tǒng)/后臺查詢的 user 記為源碼將其視同無執(zhí)行者處理不會丟棄整行也不會因構(gòu)造 URN 失敗而中斷。總結(jié)sql-queries是 DataHub 血緣體系中對查詢?nèi)罩拘驮獢?shù)據(jù)源的標(biāo)準(zhǔn)答案它用一個(gè) JSONL 文件加一個(gè) recipe 即可完成從 SQL 日志到血緣、查詢實(shí)體、使用統(tǒng)計(jì)與操作事件的完整攝取天然適合離線回填與多云日志統(tǒng)一治理。其源碼sql_queries.py與集成測試test_sql_queries.py為生產(chǎn)落地提供了完整的配置參考、容錯(cuò)策略與驗(yàn)證樣例——在接入自己的查詢?nèi)罩厩敖ㄗh先用倉庫中的樣例 JSONL 文件跑通端到端鏈路再逐步替換為真實(shí)數(shù)據(jù)源并調(diào)優(yōu)temp_table_patterns、default_db/default_schema等血緣質(zhì)量相關(guān)配置?!久赓M(fèi)下載鏈接】datahubThe Context Platform for your Data and AI Stack項(xiàng)目地址: https://gitcode.com/GitHub_Trending/da/datahub創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考