Định dạng tệp Parquet: Giải pháp lưu trữ cột cho xử lý Big Data
8/23/2025•10 mins read
Apache Parquet là một định dạng tệp dữ liệu theo cột (columnar) mã nguồn mở, được thiết kế tối ưu cho lưu trữ và truy vấn dữ liệu lớn. Ban đầu do Twitter và Cloudera phát triển (2013), Parquet nay trở thành thành phần then chốt của hệ sinh thái Hadoop và được tích hợp sâu với các công cụ xử lý dữ liệu như Apache Spark, Hive, Presto/Trino cũng như các dịch vụ kho dữ liệu đám mây hàng đầu.
Không giống CSV/JSON chỉ lưu row-by-row, Parquet ghi dữ liệu theo cột, cho phép các truy vấn phân tích chỉ phải đọc những cột cần thiết, giảm thiểu I/O đĩa và tăng tốc đáng kể hiệu năng truy vấn. Định dạng này cũng tự mô tả bản thân bằng cách lưu kèm metadata và schema trong file dữ liệu, nhờ đó hỗ trợ khả năng thay đổi cấu trúc schema (thêm/bỏ cột) một cách linh hoạt mà không làm gián đoạn pipeline.
Các cột trong Parquet còn được nén và mã hóa hiệu quả (hỗ trợ Snappy, Gzip, Brotli, LZO, v.v.), giúp giảm dung lượng lưu trữ (thường nhỏ hơn CSV/JSON khoảng 2–5 lần) và tiết kiệm băng thông khi truy vấn. Nhờ đó, Parquet trở thành lựa chọn ưu tiên cho các pipeline ETL xử lý hàng tỷ bản ghi, cũng như các giải pháp kho dữ liệu và báo cáo phân tích lớn.
Ưu điểm kỹ thuật của Parquet
Parquet đem lại nhiều lợi thế đáng kể so với định dạng truyền thống, đặc biệt trong các kịch bản OLAP và Big Data:
Lưu trữ theo cột (Columnar)
Thay vì lưu cùng một hàng dữ liệu nối tiếp (như CSV, JSON), Parquet lưu từng cột riêng lẻ. Khi truy vấn chỉ cần đọc một vài cột cụ thể, Parquet có thể bỏ qua các cột còn lại, giảm I/O xuống mức tối thiểu. Các benchmark của Databricks cho thấy Parquet có thể đọc nhanh hơn 10–100 lần so với CSV/JSON trong các truy vấn phân tích cột.

Nén dữ liệu cao và mã hóa thông minh
Parquet hỗ trợ nhiều thuật toán nén (Snappy, Gzip, LZO, Brotli, ZSTD…) và nhiều phương thức mã hóa (dictionary encoding, run-length encoding, delta encoding…) trên từng cột riêng biệt. Điều này cho phép giảm rất tốt các giá trị lặp (dictionary encoding) hay giá trị giống nhau liên tiếp (run-length), từ đó dung lượng file Parquet thường chỉ bằng 1/2–1/5 so với dữ liệu thô trên CSV/JSON. Ví dụ, Google BigQuery lưu ý rằng dùng Parquet sẽ giảm đáng kể bytes phải quét trong truy vấn, tiết kiệm thời gian và chi phí tính toán.
Hỗ trợ schema mạnh mẽ
Parquet là định dạng có self-describing schema – metadata (bao gồm kiểu và cấu trúc các cột) được lưu cùng dữ liệu. Nó cho phép schema evolution, tức có thể thêm, đổi tên, hoặc xóa cột mà không phải ghi lại toàn bộ dữ liệu cũ. Các công cụ như Spark, Hive, AWS Glue đều tự động xử lý schema evolution của Parquet, đảm bảo khả năng tương thích tiến và lùi giữa các version dữ liệu.

Xử lý dữ liệu phức tạp
Parquet hỗ trợ trực tiếp các kiểu dữ liệu phức tạp như struct, array, map,… mà không cần phải flatten (mở rông) về các cột đơn giản. Dữ liệu lồng nhau (nested) và kiểu tổ hợp được bảo lưu trên Parquet và được tối ưu nhờ định dạng tương thích với Apache Arrow. Nhờ vậy, Parquet cho phép truy vấn nhanh hơn và tiết kiệm hơn với các trường phức tạp so với định dạng JSON thuần túy. Nhiều nền tảng lớn (Snowflake, Databricks) đều dùng Parquet để lưu trữ các mô hình dữ liệu phức tạp như session logs, event data, v.v.
Tương thích rộng và đa nền tảng
Parquet được hỗ trợ "out-of-box" trên hầu hết hệ thống xử lý dữ liệu lớn. Các công cụ phổ biến như Apache Spark, Hive, Presto/Trino, Apache Drill, AWS Athena, Google BigQuery… đều có thể đọc/ghi Parquet một cách sẵn sàng. Ngoài ra, Parquet có thư viện đọc/ghi cho nhiều ngôn ngữ (Java, Scala, Python/PyArrow, Pandas, Dask,…) nên dễ tích hợp trong môi trường cloud hoặc on-premise mà không phụ thuộc nhà cung cấp. Khả năng tương thích này giúp tránh bị "lock-in" về định dạng, cho phép chuyển đổi dữ liệu linh hoạt giữa các công cụ mà không phải viết lại ETL.
So sánh Parquet với CSV, JSON, Avro
Khi chọn định dạng dữ liệu cho phân tích, cần hiểu sự khác biệt giữa Parquet và các định dạng phổ biến khác như CSV, JSON, Avro. Các định dạng dòng (row-based) như CSV hay JSON lưu toàn bộ một bản ghi (hàng) liên tục, trong khi Parquet lưu theo cột. Như Airbyte đã chỉ ra, ở định dạng dòng, hệ thống phải đọc toàn bộ các cột của hàng cho dù truy vấn chỉ cần vài cột nhất định, dẫn đến nhiều dữ liệu không cần thiết bị đọc vào bộ nhớ. Trong khi đó, định dạng cột của Parquet cho phép predicate pushdown (lọc dữ liệu ngay ở tầng lưu trữ) và column pruning (bỏ qua dữ liệu thừa), giảm mạnh I/O và tăng tốc truy vấn.
Cụ thể, theo bảng so sánh của EdgeDelta, Parquet có lợi thế vượt trội về tốc độ đọc và nén so với CSV/JSON và Avro. CSV là định dạng văn bản đơn giản, dễ đọc và tương thích với nhiều công cụ (Excel, Sheets), nhưng nó không chứa thông tin schema và không nén dữ liệu – kết quả là khi lưu dữ liệu lớn, CSV rất tốn không gian và truy vấn chậm. JSON hỗ trợ cấu trúc lồng nhau nhưng cũng là định dạng text và schema-less, nên file JSON cũng cồng kềnh và tốn chi phí parse. Avro, ngược lại, là định dạng nhị phân (binary) có schema tích hợp tốt – giúp serialization/streaming nhanh – nhưng vì lưu trữ theo hàng nên không thể bỏ qua cột khi truy vấn cột đơn, do đó tốc độ truy vấn dạng OLAP kém hơn Parquet.
Tóm lại, Parquet và ORC luôn dẫn đầu cho phân tích dữ liệu (băng thông cao, query nhanh), trong khi Avro/Protobuf ưu thế ở các pipeline streaming và serialization nhanh, còn CSV/JSON thường chỉ dùng cho các trường hợp đọc/viết file đơn giản, debug hoặc xử lý config nhẹ. Việc hiểu rõ trade-off này giúp kỹ sư dữ liệu chọn đúng định dạng cho từng giai đoạn: ví dụ, dùng CSV/JSON cho bước đầu ingest nhanh, Avro cho stream/nhắn tin, và Parquet cho lưu trữ lâu dài phục vụ báo cáo phân tích.

Sử dụng Parquet trong Spark, Hive và Presto
Các hệ thống Big Data hiện nay đều tích hợp sẵn khả năng làm việc với Parquet. Trong Apache Spark, API DataFrame rất dễ dùng: chỉ cần df.write.parquet(path) để ghi DataFrame ra file Parquet, và spark.read.parquet(path) để đọc lại mà không mất schema. Khi Spark SQL đọc Parquet, nó tự động duy trì thông tin schema và chuyển tất cả cột thành nullable để đảm bảo tương thích, nhờ vậy việc load dữ liệu Parquet luôn nhanh và "dễ chịu" hơn định dạng text.
Trong Apache Hive, từ phiên bản 0.13 trở đi đã hỗ trợ Parquet một cách nguyên thủy. Ví dụ, để tạo bảng Hive lưu ở định dạng Parquet, ta chỉ cần câu lệnh:
SQLCREATE TABLE table_name ( ... )
PARTITIONED BY (...)
STORED AS PARQUET;
Hướng dẫn chính thức của Hive cũng nêu rõ cú pháp này để khởi tạo bảng Parquet. Hive sẽ tự động map các file Parquet vào cấu trúc bảng với kiểu dữ liệu tương ứng. Các hệ thống dựa trên Hive (như Amazon Athena, Presto sử dụng Hive Metastore) cũng do đó có thể query trực tiếp các file Parquet đặt trên S3 hoặc HDFS mà không cần chuyển đổi.
Còn Presto/Trino (cùng với các dịch vụ tương tự Athena, BigQuery) cũng mặc định hỗ trợ Parquet. Parquet được xem là "định dạng chuẩn" của các công cụ truy vấn dạng phân tán – chúng đọc từng cột khi xử lý truy vấn và tận dụng metadata Parquet (min/max stats) để skip dữ liệu nhanh. Như Airbyte nhấn mạnh, Parquet đã trở thành "định dạng bậc nhất" cho Spark, Hive, Presto/Trino và hầu hết các kho dữ liệu đám mây. Nhờ đó, quy trình ETL thường xuyên sử dụng Parquet làm layer lưu trữ trung gian hoặc đích, tạo sự thống nhất giữa các công cụ tính toán và giảm thiểu overhead khi truyền dữ liệu giữa chúng.
Ví dụ thực tế về sử dụng Parquet
Trong thực tế, Parquet được ứng dụng rộng rãi trong các pipeline dữ liệu và kho dữ liệu (data warehouse). Ví dụ, một công ty phân tích rủi ro xây dựng pipeline Big Data trên AWS như sau: dữ liệu thô đầu vào (ở dạng CSV) được nạp vào Amazon S3, xử lý bởi AWS Glue/Spark để kiểm tra và biến đổi, sau đó lưu trữ kết quả dưới dạng Parquet trên S3. Dữ liệu Parquet này (đã chuyển về format "dài" để tối ưu truy vấn) sau đó được cung cấp cho các hệ thống downstream (ví dụ dashboard BI, ETL tiếp theo) để phân tích và báo cáo. Nhờ Parquet, hệ thống có thể truy vấn hàng tỷ dòng dữ liệu trên S3 rất nhanh và tốn ít chi phí hơn so với dùng CSV/JSON.
Một minh họa khác từ Google BigQuery cho thấy lợi ích cụ thể của Parquet: giả sử bộ dữ liệu 1 TB được lưu dưới dạng CSV thì chi phí tính toán và lưu trữ rất cao. Khi chuyển sang Parquet, kích thước thực tế chỉ còn ~130 GB và thời gian chạy truy vấn giảm từ 236 giây xuống 6,78 giây (tăng tốc ~34 lần). Thực tế này cho thấy dữ liệu Parquet ít phải scan hơn (giảm đến ~99%), dẫn đến tiết kiệm chi phí đáng kể trên các nền tảng query tính theo bytes quét. Theo Databricks, đổi sang Parquet có thể giúp tiết kiệm khoảng 87% dung lượng lưu trữ và tăng tốc độ truy vấn trung bình 34 lần so với CSV trong BigQuery. Thậm chí, Google Cloud khuyến nghị dùng Parquet trong BigQuery để "tiết kiệm thời gian và tiền bạc" nhờ quét ít dữ liệu hơn.
Tóm lại, các ví dụ thực tế cho thấy Parquet phù hợp cho tất cả giai đoạn lưu trữ dữ liệu lớn: từ data lake trên S3/ADLS đến data warehouse trên cloud (Amazon Redshift Spectrum, Azure Synapse, Snowflake, BigQuery…) hoặc môi trường Spark/Hadoop. Các công cụ phân tích và ETL hiện nay đều tận dụng Parquet làm định dạng chung để tối ưu hiệu năng, đồng thời tiết kiệm chi phí hạ tầng.
Lưu ý và best practices khi sử dụng Parquet
Dù mạnh mẽ, Parquet cũng có một số hạn chế và yêu cầu lưu ý đặc thù. Đầu tiên, vì là định dạng nhị phân (binary), Parquet không thể mở trực tiếp bằng trình soạn thảo văn bản. Kỹ sư dữ liệu cần các công cụ chuyên dụng (Apache Arrow, parquet-tools, notebook, v.v.) để kiểm tra hoặc debug file Parquet. Ngoài ra, Parquet được thiết kế để tối ưu cho đọc và xử lý batch lớn, nên ghi (write) Parquet sẽ có overhead cao hơn: mỗi lần ghi phải tổ chức lại thành các cột, mã hóa và nén, tiêu tốn CPU/IO nhiều hơn. Điều này khiến Parquet không lý tưởng cho các workload ghi nhỏ lẻ, streaming logs hoặc ghi cập nhật thường xuyên. Nếu hệ thống cần ghi real-time hoặc nhiều bản ghi cập nhật, định dạng như Avro hay JSON (không nén, ghi nhẹ) có thể phù hợp hơn.
Dưới đây là một số best practices để tối ưu Parquet trong pipeline:
Chọn kích thước Row Group phù hợp
Row group là đơn vị lưu trữ chính của Parquet. Row group quá nhỏ gây overhead metadata lớn, quá lớn lại tốn nhiều bộ nhớ khi đọc. Thông thường nên hướng tới size ~128–512 MB cho mỗi row group, cân bằng giữa tăng cường skip dữ liệu và khả năng song song trên Spark/SparkSQL.
Phân vùng dữ liệu (Partitioning)
Chia bộ dữ liệu thành các thư mục con theo giá trị của các cột thường dùng trong truy vấn (ví dụ theo ngày tháng, region…). Partitioning giúp query chỉ truy vấn các phân vùng liên quan và bỏ qua hoàn toàn các folder không cần thiết. Ví dụ, dữ liệu thời gian có thể phân vùng theo ngày, cho phép hệ thống truy vấn bỏ qua các thư mục ngày khác.
Sử dụng nén Snappy mặc định
Snappy là codec nén nhanh, cho tỷ lệ nén chấp nhận được nhưng decode cực nhanh, rất phù hợp đa số workload phân tích. Chỉ khi ưu tiên tiết kiệm dung lượng tối đa, có thể cân nhắc Gzip/Brotli (nén tốt hơn nhưng chậm hơn) hoặc Zstandard (tùy chỉnh cao).
Kích hoạt predicate pushdown
Đảm bảo hệ thống truy vấn (Spark, Presto, v.v.) được cấu hình để dùng predicate pushdown, nghĩa là sử dụng thống kê min/max tại mỗi column-chunk để lọc sớm dữ liệu. Điều này cho phép Parquet skip cả row group không thỏa điều kiện mà không phải giải mã chúng.
Lựa chọn mã hóa dữ liệu thông minh
Parquet có nhiều phương thức mã hóa. Ví dụ, dùng dictionary encoding cho cột có ít giá trị phân biệt (như cột danh mục, ID lặp), run-length encoding (RLE) cho cột có nhiều giá trị giống nhau liên tiếp (như cờ, boolean), delta encoding cho cột giá trị tăng dần (như timestamp, số thứ tự). Kỹ thuật này có thể giảm đáng kể kích thước và tăng tốc giải nén.
Tránh quá nhiều file nhỏ
Trong hệ phân tán, mỗi file Parquet nhỏ đều kèm metadata riêng và gây overhead I/O mỗi khi mở. Việc có quá nhiều file kích thước nhỏ (<128 MB) sẽ làm chậm query do mở/đóng file liên tục. Nên gom góp, sắp xếp và ghép file lớn (khoảng 128 MB–1 GB) trước khi lưu lên data lake. Các công cụ như Spark, Hudi, Delta Lake đều hỗ trợ compact để hợp nhất file.
Sắp xếp dữ liệu theo cột truy vấn
Nếu có thể, sắp xếp bản ghi theo các cột thường xuyên lọc hoặc group by (ví dụ cột timestamp) khi ghi Parquet. Điều này giúp cải thiện hiệu quả thống kê min/max và skip dữ liệu. Ví dụ, sắp xếp theo thời gian sẽ giúp truy vấn theo khoảng thời gian bỏ qua nhanh những row group ở ngoài phạm vi.
Sử dụng lớp transaction nếu cần ACID
Trong môi trường data lakehouse (như dùng Delta Lake, Apache Iceberg, hoặc Apache Hudi), Parquet thường được kết hợp với lớp transaction để hỗ trợ ACID, time-travel và versioning. Các giải pháp này duy trì log cập nhật cho phép cập nhật/xóa dữ liệu một cách an toàn mà vẫn giữ cơ sở là file Parquet hiệu quả.
Tóm lại, tuân thủ các lưu ý và best practices trên sẽ giúp tối ưu hóa hiệu năng và chi phí của Parquet. Ngoài ra, luôn kiểm tra tương thích phiên bản và native library (ví dụ Spark/PyArrow) khi di chuyển hay nâng cấp, để đảm bảo hệ thống đọc/ghi Parquet ổn định.
Kết luận
Parquet là định dạng lưu trữ cột đã trở thành tiêu chuẩn cho kho dữ liệu và phân tích lớn. Bằng việc lưu dữ liệu theo cột, tích hợp cơ chế nén/mã hóa mạnh và hỗ trợ schema linh hoạt, Parquet giúp giảm đáng kể dung lượng lưu trữ và tăng tốc truy vấn trên bộ dữ liệu khổng lồ. Nó được hầu hết nền tảng dữ liệu lớn (Spark, Hive, Presto, Athena, BigQuery, v.v.) hỗ trợ một cách native, do đó giúp liên kết mượt mà giữa các bước xử lý trong pipeline.
Tuy Parquet mạnh trong các tình huống truy vấn phân tích (OLAP), các kỹ sư dữ liệu cần chọn đúng công cụ cho workload. Trong pipeline ETL thường dùng Parquet để lưu kết quả và phục vụ báo cáo, còn các khối ghi dữ liệu thời gian thực có thể dùng định dạng khác phù hợp. Đặc biệt, áp dụng các best practices như phân vùng hợp lý, row-group vừa phải, nén Snappy, và giảm thiểu file nhỏ sẽ tối ưu hoá hiệu năng và chi phí. Khi được sử dụng đúng cách, Parquet giúp các hệ thống Big Data chạy nhanh hơn và ít tốn kém hơn, đồng thời duy trì độ linh hoạt về cấu trúc dữ liệu trong dài hạn.
Tóm lại, Parquet là một công cụ đắc lực cho các kỹ sư dữ liệu khi làm việc với dữ liệu lớn. Hiểu rõ ưu nhược điểm và áp dụng hợp lý sẽ giúp đạt được hiệu năng cao nhất cho các workload phân tích và data warehousing hiện đại.