CSV vs Parquet in DuckDB: Which Queries Benefit from Conversion?

A monthly revenue query reads only a few columns from a large orders CSV. Will converting it to Parquet let DuckDB skip the rest, and what else decides that?

CSV vs Parquet in DuckDB: Which Queries Benefit from Conversion?
TLDR
  • Parquet can avoid reading columns and row groups a query does not need.
  • Filter pruning depends on statistics and data layout, not merely the presence of a WHERE clause.
  • For repeated, join-heavy analysis, compare direct Parquet queries with loading DuckDB tables.

Start with a query that needs less than the whole file

A monthly revenue query that needs only an order date and amount is a good candidate for Parquet. DuckDB pushes column selection and filters into its Parquet reader, allowing it to read the columns needed by the query. That includes columns used in filters and aggregates, not just the final output.

CSV stores fields together as text. DuckDB’s CSV and Parquet comparison explains that CSV projection can skip work such as casting and copying an unused value, but the reader still parses it to move past it. Parquet’s column layout lets the reader avoid unnecessary column data.

The useful question is how much work the query can skip. Selecting two columns from a wide dataset is different from exporting every value, so a speed multiplier from someone else’s benchmark is not a forecast for both.

A WHERE clause needs useful file statistics

A Parquet row group contains a chunk for each column. Statistics such as minimum and maximum values can tell DuckDB that a group cannot satisfy a filter. Pruning requires suitable metadata; a WHERE clause alone does not guarantee that parts of the file will be skipped.

Consider a query for October orders. A group containing only September dates can be excluded. If every group contains dates spanning the entire year, those ranges are much less useful. This is an illustrative layout, not a benchmark result.

Sorting by frequently filtered columns can narrow the ranges within groups. Smaller groups are not automatically better: each has metadata overhead, and full-file aggregations have different needs from selective queries.

Group layout also affects parallel scans. The performance guide explains that a file with one giant row group cannot distribute that group scan across multiple threads. A slow Parquet file deserves a layout check before concluding that the format provides no benefit.

Convert around the query you intend to run

This example assumes an orders.csv file with a DATE column named order_date and a numeric amount. Inspect the inferred types first:

DESCRIBE SELECT * FROM read_csv('orders.csv');

Once the types are correct, a sorted export can use DuckDB’s documented Parquet COPY syntax. Adjust the input query if the actual names differ or the dates were read as strings.

COPY (
  SELECT * FROM read_csv('orders.csv')
  ORDER BY order_date
) TO 'orders-sorted.parquet' (FORMAT parquet, COMPRESSION zstd);

The resulting file can be queried directly, without first creating a database table. This query totals orders for October 2026:

SELECT sum(amount) AS total_amount
FROM read_parquet('orders-sorted.parquet')
WHERE order_date >= DATE '2026-10-01'
  AND order_date < DATE '2026-11-01';

Use matching types, filters and aggregates when comparing the CSV and Parquet versions. Conversion and sorting also take time, so distinguish a one-off query from a dataset that will be read repeatedly.

Repeated joins may favor DuckDB tables

Direct Parquet access is not the only useful destination for CSV data. DuckDB’s performance guidance recommends considering database loading for repeated queries and join-heavy workloads. The native format provides additional statistics that can improve join ordering.

WorkloadCandidateReason
Small files for inspection, editing or exchangeCSVReadable text works with familiar tools.
Selected columns and date ranges in large filesDirect Parquet queriesColumn selection and row-group pruning can reduce reads.
Repeated joins over the same dataDuckDB tablesRicher statistics and repeated-query performance can justify loading.

Choose a representative query before choosing the format. Test Parquet when it can skip substantial data; include loading time and storage space when comparing it with native DuckDB tables.