Parquet, globs and partitions

DuckDB · Practical · 12 min

Real datasets are folders of files; reading them as one table with pruning is what makes DuckDB scale.

A glob in the path reads many files as one table: FROM 'logs/*.parquet' or 'data/**/*.csv' (** recurses). You can also pass a list: read_parquet(['a.parquet', 'b.parquet']). Add filename = true to know which file each row came from, and union_by_name = true when files have different column sets.

Data lakes often use Hive partitioning: folders named key=value, e.g. sales/year=2025/month=03/part-0.parquet. With hive_partitioning = true (auto-detected for such paths) the folder keys become columns, and a filter like WHERE year = 2025 skips whole folders without opening them.

Parquet makes queries cheap in two more ways:

  • projection pushdown: only the columns in the query are read
  • filter pushdown: each row group stores min/max statistics, so groups that cannot match a WHERE condition are skipped

parquet_metadata('file.parquet') and parquet_schema(...) show row groups, statistics and types. All of this works the same on S3 or HTTPS paths, where skipping data saves network transfer as well as CPU.

Example

import duckdb, os, tempfile

os.chdir(tempfile.mkdtemp())
duckdb.sql("""
    COPY (SELECT i AS id, i % 3 AS shop, 2024 + i % 2 AS year FROM range(12) t(i))
    TO 'sales' (FORMAT parquet, PARTITION_BY (year))
""")
print(sorted(os.listdir("sales")))       # ['year=2024', 'year=2025']

print(duckdb.sql("""
    SELECT year, count(*) AS n, sum(id) AS ids
    FROM read_parquet('sales/*/*.parquet', hive_partitioning = true)
    WHERE year = 2025 GROUP BY year
""").fetchall())                          # [(2025, 6, 36)]

Remember

  • Globs (*, **) and lists read many files as one table
  • Hive key=value folders become columns and allow partition pruning
  • Parquet reads only needed columns and skips row groups using min/max stats

Watch out for

  • Using thousands of tiny Parquet files; per-file overhead dominates. Aim for files of tens to hundreds of MB.

Check yourself

  1. With files under sales/year=2024/ and sales/year=2025/, what does WHERE year = 2025 let DuckDB do?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: duckdb.org/docs/current/data/multiple_files/overview