Apache Parquet 文件組織結構

簡要概述

Apache Parquet 是一個開源列式存儲文件格式,最初由 Twitter 與 Cloudera 聯合開發,旨在提供高效的壓縮與編碼方案以支持大規模復雜數據的快速分析與處理。Parquet 文件采用分離式元數據設計 —— 在數據寫入完成后,再追加文件級元數據(包括 Schema、Row Group 與 Column Chunk 的偏移信息等),使得寫入過程只需一次順序掃描,同時讀取端只需先解析元數據即可隨機訪問任意列或任意 Row Group。其核心結構包括:

  1. Header(魔數“PAR1”)
  2. 若干 Row Group(行組)
  3. Footer(文件級元數據 + 魔數“PAR1”)

文件格式總體布局

1. Header(文件頭)

  • 文件以4字節的魔數 PAR1 開始,標識這是一個 Parquet 文件格式。

2. Row Group(行組)

  • Row Group 是水平切分的數據分片,每個 Row Group 包含表中若干行,通常大小在幾十 MB 到幾百 MB 之間,以兼顧并行處理與內存使用。
  • 每個 Row Group 內部再按列拆分為若干 Column Chunk,支持對單個列或多個 Row Group 進行跳過式讀取。

3. Column Chunk(列區塊)

  • Column Chunk 即某一列在某個 Row Group 中的數據塊,它是 Parquet 最基本的物理存儲單元之一。
  • 每個 Column Chunk 中又分成多個Page,以便更細粒度地管理壓縮與解壓效率。

4. Page(頁)

  • Page 是 Column Chunk 中的最小讀寫單元,主要有三種類型:
    • Dictionary Page:存放字典編碼字典。
    • Data Page:存放實際列數據(可進一步分為 Data Page V1/V2)。
    • Index Page(可選):存放 Page-level 索引,加速定位。
  • 通過 Page 級別的壓縮與編碼,Parquet 能夠對不同類型的數據采用最優策略,極大提升 I/O 性能。

5. Footer(文件尾)

  • 寫入完全部 Row Group 后,接著寫入File Metadata,其中包含:
    • Schema 定義
    • 每個 Row Group 的偏移及長度
    • 每個 Column Chunk 的偏移、頁信息、編碼與壓縮算法
  • 最后再寫入 4 字節魔數 PAR1,完整標識文件結束。

元數據管理

  • Thrift 定義:Parquet 使用 Apache Thrift 描述元數據結構(Schema、Row Group 元信息、Column Chunk 元信息、Page Header 等),以保證跨語言支持。
  • 單次寫入:由于元數據緊跟數據之后寫入,寫入端無需回寫或多次掃描,保證單次順序寫入效率。
  • 快速讀取:讀端先讀取文件末尾的 Footer,加載所有元數據后即可隨機、并行地讀取任意列與任意 Row Group,極大減少磁盤 I/O 與網絡傳輸開銷。

編碼與壓縮技術

字典編碼(Dictionary Encoding)

  • 針對低基數(unique values 較少)的列,自動開啟字典編碼,將原值映射到字典索引,從而顯著減少存儲量。

混合 RLE + Bit-Packing

  • Parquet 對整數類型實現了混合 RLE(Run-Length Encoding)與Bit-Packing,根據數據分布動態選擇最佳方案,例如對于長串相同值使用 RLE,對于小整數值使用 Bit-Packing。

其它壓縮算法

  • 支持 Snappy、Gzip、LZO、Brotli、ZSTD、LZ4 等多種壓縮格式,可按列靈活選擇。

寫入過程原理

  1. Schema 序列化:將 DataFrame/表結構映射為 Thrift Schema。
  2. Row Group 切分:按預設行數或大小切分成多個 Row Group。
  3. Column Chunk 生成:對每個列分別收集數據,分 Page 編碼與壓縮。
  4. 順序寫入:先寫 Header → 各 Row Group 的 Column Chunk(含 Page)→ Footer(含全部元數據)→ 終止魔數。

讀取過程原理

  1. 讀取 Footer:讀取文件末尾 8 字節(4 字節元數據長度 + 4 字節魔數),定位并加載全部元數據。
  2. 篩選元數據:根據查詢列與過濾條件,決定需要加載的 Column Chunk 與 Page 位置。
  3. 隨機/并行讀取:直接跳轉到各 Column Chunk 的偏移位置,按需加載并解壓 Page。
  4. 重建記錄:將各列 Page 解碼后重組成行,供上層引擎消費。

實踐示例:使用 Python 創建并寫入 Parquet

下面示例演示如何用 pandas+pyarrow 將一個簡單表格寫入 Parquet,并簡要注釋寫入過程:

import pandas as pd# 1. 創建 DataFrame
df = pd.DataFrame({"user_id": [1001, 1002, 1003],"event": ["login", "purchase", "logout"],"timestamp": pd.to_datetime(["2025-04-20 10:00:00","2025-04-20 10:05:00","2025-04-20 10:10:00"])
})# 2. 寫入 Parquet(默認 row_group_size=64MB,可通過 partition_cols 分區)
df.to_parquet("events.parquet", engine="pyarrow", compression="snappy")
  • pandas 在內部將 DataFrame Schema 轉為 Thrift Schema;
  • 按列生成 Column Chunk 并分 Page 編碼;
  • 最后輸出 Header、Column Chunk、Footer 以及魔數字段。

1. Row Group 的概念與分割原則

  • Row Group 是 Parquet 中最小的水平切分單元,表示若干行的完整切片。一個 Parquet 文件由一個或多個 Row Group 依次組成,每個 Row Group 內部再按列拆分為若干 Column Chunk,支持列式讀寫與跳過式掃描。
  • 選擇合適的 Row Group 大小,是在I/O 效率(大塊順序讀更快)和并行度/內存占用(小塊更易并行、占用更少)間的權衡。

2. Row Group 的“大小”度量方式

Parquet 對 Row Group 的大小有兩種常見度量:

  1. 未壓縮字節數(uncompressed bytes)
  2. 行數(number of rows)
  • Parquet-Java(Hadoop/Spark 常用)中,ParquetProperties.DEFAULT_ROW_GROUP_SIZE 默認為 128 MiB(未壓縮),并以字節為單位控制切分。
  • PyArrow(Python 生態)中,row_group_size 參數實際上是以行數為單位;若不指定(None),默認值已被調整為 1 Mi 行(絕對最大值仍為 64 Mi 行)。

3. 不同實現中的默認值與推薦配置

實現 / 場景默認值推薦范圍說明
Parquet-Java128 MiB(未壓縮)512 MiB – 1 GiB(未壓縮)與 HDFS 塊大小對齊,一般 HDFS 塊也應設為 1 GiB,以便一組 Row Group 剛好填滿一個塊
Spark/HDFSspark.sql.files.maxPartitionBytes 默認 128 MiB同上Spark 會將每個 Row Group 當作一個分區,讀寫時以此并行
PyArrow1 Mi 行視數據表寬度換算成字節若表寬為 10 列、每列單元假設 4 字節,1 Mi 行 ≈ 40 MiB(未壓縮)
其他工具(如 DuckDB/Polars)通常基于“每行最大允許字節數”來推算,默認約 1 Mi 行需參考各自文檔如 Polars 中 row_group_size_bytes 默認 122 880 KiB(≈ 120 MiB)

4. Row Group 在文件中的物理結構

一個 Row Group 在文件中的布局可以抽象為:

+--------------------------------------------+
|                Row Group                  |
|  ┌───────────────────────────────────────┐ |
|  │ Column Chunk for Column 0            │ │
|  │  ┌── Page 1 (Dictionary Page?)       │ │
|  │  │   - Page Header                    │ │
|  │  │   - 字典或數據塊                    │ │
|  │  └── Page 2 (Data Page v1/v2)         │ │
|  │      - Page Header                    │ │
|  │      - 壓縮/編碼后的列數據             │ │
|  │  …                                    │ │
|  └───────────────────────────────────────┘ │
|  ┌───────────────────────────────────────┐ │
|  │ Column Chunk for Column 1            │ │
|  │   …                                   │ │
|  └───────────────────────────────────────┘ │
|                    ?                       |
|  ┌───────────────────────────────────────┐ │
|  │ Column Chunk for Column N            │ │
|  │   …                                   │ │
|  └───────────────────────────────────────┘ │
+--------------------------------------------+

同時,文件末尾的 Footer 中包含了每個 Row Group 的元數據(Thrift 定義),主要字段有:

  • total_byte_size:該 Row Group 內所有 Column Chunk 未壓縮數據總字節數
  • num_rows:該 Row Group 包含的行數
  • columns: list<ColumnChunk>:每個 ColumnChunk 的偏移、長度、編碼、壓縮算法、Page 統計等

讀寫時,寫端按序將上述 Row Group 數據寫入磁盤,待所有 Row Group 完成后再寫 Footer 與尾部魔數;讀端則先讀 Footer,加載元數據后即可隨機定位到任意 Row Group 和任意字段的 Column Chunk 進行解壓與解碼。


5. 舉例說明

假設有一個表 10 列,每列單元平均占用 4 字節,我們若以 1 Mi 行為 Row Group(PyArrow 默認值),則:

  • 未壓縮 Row Group 大小 ≈ 1 Mi × 10 列 × 4 B ≈ 40 MiB
  • 壓縮后:若使用 Snappy,通常可壓縮到 1/2 – 1/4,大約 10 MiB – 20 MiB
  • 如果改為 Parquet-Java 默認 128 MiB(未壓縮),則 Row Group 行數可按上述公式反算:128 MiB ÷ (10 × 4 B) ≈ 3.3 Mi 行。

小結

  • Row Group 大小既可以用字節也可以用行數度量,具體含義取決于所用寫入器與參數;
  • Parquet-Java 默認 128 MiB(未壓縮),官方推薦 512 MiB – 1 GiB;
  • PyArrow 默認 1 Mi 行,且新版已調整絕對最大 64 Mi 行;
  • 結構上,Row Group 包含多列的 Column Chunk,每個 Column Chunk 又由若干 Page 組成;
  • 選取合適的 Row Group 大小,可在 順序 I/O 性能并行度/內存占用 之間取得平衡。
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq# 1. 創建示例 DataFrame
df = pd.DataFrame({"user_id": [1001, 1002, 1003, 1004],"event": ["login", "purchase", "logout", "login"],"timestamp": pd.to_datetime(["2025-04-20 10:00:00","2025-04-20 10:05:00","2025-04-20 10:10:00","2025-04-20 10:15:00"])
})# 2. 寫入 Parquet(指定 row_group_size 為 2 行,以演示多個 Row Group)
pq.write_table(pa.Table.from_pandas(df), 'events.parquet', row_group_size=2)# 3. 讀取 Parquet 元數據并提取 Row Group 信息
pq_file = pq.ParquetFile('events.parquet')
row_groups = []
for i in range(pq_file.num_row_groups):rg = pq_file.metadata.row_group(i)row_groups.append({"row_group_id": i,"num_rows": rg.num_rows,"total_byte_size": rg.total_byte_size})# 4. 展示 Row Group 元數據
rg_df = pd.DataFrame(row_groups)
import ace_tools as tools; tools.display_dataframe_to_user("Row Group Metadata", rg_df)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77520.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77520.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77520.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IntelliJ IDEA 2025.1 發布 ,默認 K2 模式 | Android Studio 也將跟進

2025.1 版本已經發布&#xff0c;在此之前我們就聊過該版本的 《Terminal 又發布全新重構版本》&#xff0c;而現在 2025.1 中的 K2 模式也成為了默認選項。 可以預見&#xff0c;這個版本可能會包含不少大坑&#xff0c;為下個 Android Studio 祈禱。 首先有一點可以確定&…

云效部署實現Java項目自動化部署圖解

前言 記錄下使用云效部署Java項目&#xff0c;實現java項目一鍵化自動化部署。 云效流程說明&#xff1a; 1.云效拉取最新git代碼后 2.進行maven編譯打包后&#xff0c;上傳到指定服務器目錄 3.通過shell腳本&#xff0c;先kill java項目后&#xff0c;通過java -jar 啟動項…

國際數據加密算法(IDEA)詳解

以下是修正后的準確版本,已解決原文中的術語、符號及技術細節問題: ?國際數據加密算法(IDEA)? IDEA是一種分組加密算法,由Xuejia Lai(來學嘉)和James Massey于1990年設計。IDEA使用128位密鑰對64位明文分組進行加密,經過8輪迭代運算后生成64位密文分組。其安全性基于…

TensorFlow介紹

TensorFlow 是由 Google 開發 的開源機器學習框架&#xff0c;主要用于構建、訓練和部署機器學習模型。它支持深度學習、傳統機器學習和數值計算&#xff0c;適用于圖像識別、自然語言處理&#xff08;NLP&#xff09;、推薦系統、強化學習等多種任務。 核心特性 基于 數據流…

百級Function架構集成DeepSeek實踐:Go語言超大規模AI工具系統設計

一、百級Function系統的核心挑戰 1.1 代碼結構問題 代碼膨脹現象&#xff1a;單個文件超過2000行代碼路由邏輯復雜&#xff1a;巨型switch-case結構維護困難依賴管理失控&#xff1a;跨Function依賴難以追蹤 // 傳統實現方式的問題示例 switch functionName { case "fu…

嵌入式芯片中的 SRAM 內容細講

什么是 RAM&#xff1f; RAM 指的是“隨機存取”&#xff0c;意思是存儲單元都可以在相同的時間內被讀寫&#xff0c;和“順序訪問”&#xff08;如磁帶&#xff09;相對。 RAM 不等于 DRAM&#xff0c;而是一類統稱&#xff0c;包括 SRAM 和 DRAM 兩種主要類型。 靜態隨機存…

標準的JNI (Java Native Interface) 加載函數 JNI_OnLoad

1.JNI_OnLoad 在 Android Native 開發中&#xff0c;JNI_OnLoad 是動態注冊本地方法的標準入口點。以下是一個標準實現示例及其說明&#xff1a; JNI_OnLoad 標準實現 #include <jni.h> #include <string>// 聲明本地方法對應的 C/C 函數 jint native_add(JNIEnv…

算法導論思考題

2-1 在歸并排序中對小數組采用插入排序 c. 假定修改后的算法的最壞情況運行時間為 Θ \Theta Θ(nknlg(n/k))&#xff0c;要使修改后的算法與標準的歸并排序具有相同的運行時間&#xff0c;作為n的一個函數&#xff0c;借助 Θ \Theta Θ記號&#xff0c;k的最大值是什么&#…

JavaScript 性能優化

JavaScript 性能優化是提高 Web 應用性能的關鍵步驟,特別是在處理大量數據、復雜計算或頻繁的 DOM 操作時。以下是一些常見的 JavaScript 性能優化技巧和策略: 文章目錄 @[TOC]一、代碼層面優化1. **減少全局變量**2. **避免使用 `with` 語句**3. **使用局部變量**4. **減少 …

NLP高頻面試題(四十七)——探討Transformer中的注意力機制:MHA、MQA與GQA

MHA、MQA和GQA基本概念與區別 1. 多頭注意力(MHA) 多頭注意力(Multi-Head Attention,MHA)通過多個獨立的注意力頭同時處理信息,每個頭有各自的鍵(Key)、查詢(Query)和值(Value)。這種機制允許模型并行關注不同的子空間上下文信息,捕捉復雜的交互關系。然而,MHA…

51單片機的原理圖和PCB繪制

51單片機最小系統原理圖 加了兩個led燈和按鍵檢測電路。 PCB中原件擺放位置 成品 資源鏈接&#xff1a;https://download.csdn.net/download/qq_61556106/90656365

使用注解方式整合ssm時,啟動tomcat掃描不到resource下面的xxxmapper.xml

解決org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.mapper.方法 在Spring與Mybatis整合時&#xff0c;可能會遇到這樣的報錯 原因&#xff1a; 其原因為mapper路徑的映射錯誤&#xff0c;表示在嘗試執行某個 Mapper 接口的方法時…

提示詞設計:動態提示詞 標準提示詞

提示詞設計:動態提示詞 標準提示詞 研究背景:隨著人工智能與司法結合的推進以及裁判文書公開數量增多,司法摘要任務愈發重要。傳統司法摘要方法生成質量有待提升,大語言模型雖有優勢,但處理裁判文書時存在摘要結構信息缺失、與原文不一致等問題。研究方法 DPCM方法:分為大…

Jenkins 多分支管道

如果您正在尋找一個基于拉取請求或分支的自動化 Jenkins 持續集成和交付 (CI/CD) 流水線&#xff0c;本指南將幫助您全面了解如何使用 Jenkins 多分支流水線實現它。 Jenkins 的多分支流水線是設計 CI/CD 工作流的最佳方式之一&#xff0c;因為它完全基于 git&#xff08;源代…

跨境電商管理轉型:日事清通過目標管理、流程自動化助力智優美科技項目管理升級與目標落地復盤

1.客戶背景介紹 深圳市智優美科技有限公司是一家專業從事外貿B2C的電子商務公司&#xff0c;公司總部位于深圳市寶安區&#xff0c;旗下擁有三家子公司。目前銷售的品類有&#xff1a;家居用品、電子產品、電子配件產品等&#xff0c;在深圳外貿電商行業銷售額穩居行業前10名。…

基于Docker+k8s集群的web應用部署與監控

項目架構圖 server ip master 192.168.140.130 node1 192.168.140.131 node2 192.168.140.132 ansible 192.168.140.166 jumpserver 192.168.100.133 firewall 192.168.1.86 nfs 192.168.140.157 harbor 192.168.140.159 Promethethus 192.168.140.130 Jen…

量子計算與經典計算融合:開啟計算新時代

一、引言 隨著科技的飛速發展&#xff0c;計算技術正迎來一場前所未有的變革。量子計算作為前沿技術&#xff0c;以其強大的并行計算能力和對復雜問題的高效處理能力&#xff0c;吸引了全球科技界的關注。然而&#xff0c;量子計算并非要完全取代經典計算&#xff0c;而是與經典…

【HarmonyOS 5】makeObserved接口詳解

【HarmonyOS 5】makeObserved接口詳解 一、makeObserved接口是什么&#xff1f; makeObserved 接口&#xff08;API version 12 起可用&#xff09;用于將非觀察數據轉為可觀察數據&#xff0c;適用于三方包類、Sendable 裝飾的類、JSON.parse 返回的對象、collections.Array…

豆瓣圖書數據采集與可視化分析(二)- 豆瓣圖書數據清洗與處理

文章目錄 前言一、查看數據基本信息二、拆分pub列三、日期列處理四、價格列處理五、出版社列處理六、評價人數列處理七、缺失值處理八、重復數據處理九、異常值處理十、完整代碼十一、清洗與處理后的數據集展示 前言 豆瓣作為國內知名的文化社區&#xff0c;擁有龐大且豐富的圖…

Wasm -WebAssembly簡介

WebAssembly 是什么&#xff1f; WebAssembly/wasm WebAssembly 或者 wasm 是一個可移植、體積小、加載快并且兼容 Web 的全新格式 WebAssembly&#xff08;簡稱 Wasm&#xff09;是一種二進制指令格式&#xff0c;設計用于在現代 Web 瀏覽器中高效運行程序。它可以被認為是一…