Parquet Performance Tuning: 8 Best Practices
Tune Apache Parquet for speed and cost: row group and file sizes, partitioning, Snappy vs ZSTD compression, encodings, sorting, and predicate pushdown.

Throughout this series, we’ve explored the many features that make Apache Parquet a powerful and efficient file format for big data processing. In this final post, we’ll focus on performance tuning and best practices to help you optimize your Parquet workflows. Whether you’re working in a data lake, a data warehouse, or a data lakehouse, following these guidelines will help you get the most out of your Parquet data.
Reviewed October 15, 2026 against the Parquet configuration docs and Apache Iceberg’s table configuration defaults.
Cross-posted. This article’s canonical home is Alex Merced’s Lakehouse Blog.
- Free Copy of Apache Iceberg the Definitive Guide
- Free Apache Iceberg Crash Course
- Iceberg Lakehouse Engineering Video Playlist
Why Performance Tuning Matters
When dealing with large datasets, even small inefficiencies can lead to significant slowdowns and increased costs. Properly tuning Parquet files can:
- Improve query performance: By reducing the amount of data read from disk and optimizing how data is processed, you can drastically speed up analytical queries.
- Reduce storage costs: Compression and partitioning techniques reduce storage usage, lowering the costs associated with cloud object storage or on-premise data infrastructure.
- Enhance scalability: By optimizing how data is structured and accessed, Parquet can scale efficiently as your data grows, supporting high-performance analytics on petabytes of data.
Best Practices for Optimizing Parquet
Let’s dive into some key strategies to optimize the performance of Parquet files in your data pipelines.
1. Choose the Right Row Group Size
Row groups are the primary unit of storage and processing in Parquet files. Each row group contains data for a subset of rows, stored in column chunks. Choosing the right row group size is critical for performance:
- Larger row groups reduce metadata overhead and improve read performance by reducing the number of I/O operations required to scan the data. However, larger row groups can lead to higher memory consumption during query execution.
- Smaller row groups allow for better parallelism and more granular data skipping but may increase the amount of metadata and result in slower queries.
Best Practice: Common writers default to 128 MB row groups (Apache Iceberg’s default), while the Parquet project itself recommends large row groups of 512 MB to 1 GB. Start at 128 MB and go larger for scan-heavy workloads if your engines have the memory. This balances I/O efficiency and query parallelism in distributed systems like Apache Spark or Dremio.
2. Partition Your Data
Partitioning your Parquet data can significantly improve query performance by allowing query engines to skip over irrelevant partitions. Partitioning divides a dataset into smaller files or folders based on the values of one or more columns, typically ones frequently used in queries (e.g., date, region, or product category).
For example, if your dataset contains a date column, partitioning by date will create folders for each date, allowing query engines to ignore entire date ranges that are not relevant to the query.
Best Practice: Partition data by columns that are frequently used in filters and where the cardinality (the number of distinct values) is relatively low. Over-partitioning (too many small partitions) can lead to excessive file fragmentation, while under-partitioning can result in reading too much unnecessary data.
3. Leverage Compression Wisely
Parquet supports several compression algorithms, each with different trade-offs between compression ratio, speed, and CPU usage. Choosing the right compression algorithm depends on your priorities:
- Snappy: Fast compression and decompression with a moderate compression ratio. Ideal for real-time analytics and interactive queries.
- Gzip: Higher compression ratio but slower, making it suitable for datasets where storage savings are prioritized over query speed.
- Brotli: Similar to Gzip but offers better decompression performance, useful when both storage and read performance are important.
- Zstandard (ZSTD): Highly configurable with a good balance of speed and compression ratio, making it a strong option for both storage efficiency and performance.
Best Practice: Snappy is still a common default for speed, but ZSTD has become the default in many lakehouse tools (Apache Iceberg writes Parquet with ZSTD by default) because it usually produces noticeably smaller files with similar read speed. Use Gzip or Brotli only when storage costs outweigh CPU costs.
4. Use Predicate Pushdown
Predicate pushdown allows query engines to filter data at the file or row group level, reducing the amount of data that needs to be scanned. Parquet supports min/max statistics at the column and row group level, which allows query engines to skip entire row groups or pages that do not match the query filter.
For example, if your query filters for rows where the Age column is greater than 30, Parquet can skip row groups where the maximum value of Age is less than or equal to 30.
Best Practice: Ensure that your data processing frameworks (e.g., Apache Spark, Presto, Dremio) are configured to use predicate pushdown. Also, keep row group sizes large enough to ensure effective use of Parquet’s built-in statistics.
5. Optimize Encoding Strategies
Parquet supports a variety of encoding techniques that optimize how data is stored within each column, including dictionary encoding, run-length encoding (RLE), and delta encoding. The right encoding can significantly reduce file size and improve read performance:
- Dictionary encoding: Great for columns with repeated values, like categories, status codes, or foreign keys. Reduces storage by replacing repeated values with references to a dictionary.
- Run-length encoding (RLE): Ideal for columns with long runs of the same value, such as binary flags or sorted columns.
- Delta encoding: Works well for columns with values that are close together or increase in a predictable pattern, such as timestamps or IDs.
Best Practice: Most writers apply dictionary encoding automatically and fall back to plain encoding when a column’s dictionary grows too large. Help them by keeping low-cardinality columns as plain strings or integers, and consider delta encoding for sorted or sequential data such as timestamps. These optimizations can significantly reduce storage and improve query efficiency.
6. Avoid Small Files
In distributed data systems, small files can become a performance bottleneck. Each file carries metadata overhead and incurs an I/O cost to open and read, so working with too many small files can slow down query execution. This is a common issue in data lakes and lakehouses where data is ingested in small batches.
Best Practice: Consolidate small files into larger Parquet files whenever possible. Aim for file sizes in the range of 128 MB to 1 GB, depending on your system’s memory and processing capacity. Table formats handle this for you: Apache Iceberg’s rewrite_data_files procedure, Delta Lake’s OPTIMIZE, and Apache Hudi’s clustering service all combine small files into larger ones.
7. Monitor and Optimize Data Layout
Data layout plays a crucial role in query performance. Sorting your data by frequently queried columns can improve the effectiveness of min/max statistics and predicate pushdown, allowing query engines to skip irrelevant data.
For example, sorting a dataset by timestamp can improve the performance of time-range queries, as Parquet can quickly skip over rows outside the specified time window.
Best Practice: Sort your data by columns frequently used in filters or range queries. This improves the efficiency of Parquet’s statistics and query pruning mechanisms.
8. Use Transactional Layers for Consistency
In data lakehouse environments, you can use transactional table formats like Apache Iceberg, Delta Lake, or Apache Hudi on top of Parquet to enforce ACID (Atomicity, Consistency, Isolation, Durability) transactions. These layers ensure data consistency during concurrent reads and writes, allow for schema evolution, and enable advanced features like time-travel queries and snapshot isolation.
Best Practice: Implement a transactional table format if you need ACID guarantees, versioning, or schema management in your data lake. These layers provide additional optimization for managing large-scale Parquet data.
Frequently Asked Questions
What is the best row group size for Parquet?
Apache Iceberg defaults to 128 MB row groups, and the Parquet project recommends large row groups of 512 MB to 1 GB. Start around 128 MB and go larger for scan-heavy analytics if your engines have the memory.
Should I use Snappy or ZSTD for Parquet compression?
Snappy is fast and widely supported, but ZSTD usually produces noticeably smaller files with similar read speed, which is why Apache Iceberg now writes Parquet with ZSTD by default. Use Gzip or Brotli only when storage cost outweighs CPU cost.
What file size should Parquet files be?
Aim for roughly 128 MB to 1 GB per file. Apache Iceberg targets 512 MB by default. Many small files add metadata and open-file overhead, so compact them with tools like Iceberg’s rewrite_data_files or Delta Lake’s OPTIMIZE.
How does sorting improve Parquet query performance?
Sorting by a frequently filtered column tightens the min and max statistics stored for each row group and page. Engines can then skip more data during predicate pushdown, especially for range filters on timestamps or IDs.
Conclusion
Parquet’s powerful combination of columnar storage, compression, and rich metadata makes it an ideal file format for large-scale data storage and analytics. By following best practices around row group sizing, partitioning, compression, and encoding, you can further optimize your Parquet workflows for both performance and cost efficiency.
Whether you’re working in a cloud-based data lake, a data warehouse, or a modern data lakehouse, tuning your Parquet files ensures that your queries run faster, your storage footprint is minimized, and your data infrastructure scales effectively.
This concludes our 10-part series on the Parquet file format. We hope this deep dive has given you a solid understanding of Parquet’s capabilities and how to harness them in your data engineering projects.
Thank you for following along, and feel free to revisit any part of the series as you continue optimizing your Parquet workflows!


