# Read a Parquet file

Acquire / file

A variant of [Read a columnar file](https://meridian.online/operations/read-a-columnar-file).

Read one or many Parquet files into a table, reading only the columns and row groups the query needs.

Page: <https://meridian.online/operations/read-a-columnar-file/read-a-parquet-file>

## Status

Runs as a SQL step.

arcform carries it as a `sql:` step today.

## The DuckDB step

read many Parquet files with only the columns and row groups a query needs

```sql
-- two files of two row groups each; the amounts rise with the order number, so each row group covers a range of amounts
COPY (SELECT i AS order_id, 'c' || (i % 7) AS customer, i::DECIMAL(8, 2) AS amount, repeat('x', 20) AS pad FROM range(1, 4097) t(i))
  TO '<your_scratch_dir>/pq_a.parquet' (FORMAT parquet, ROW_GROUP_SIZE 2048);
COPY (SELECT i AS order_id, 'c' || (i % 7) AS customer, i::DECIMAL(8, 2) AS amount, repeat('x', 20) AS pad FROM range(4097, 8193) t(i))
  TO '<your_scratch_dir>/pq_b.parquet' (FORMAT parquet, ROW_GROUP_SIZE 2048);
-- two files by one glob, two columns out of four, and a filter the row-group statistics can answer
CREATE TEMP TABLE result AS
SELECT customer, amount FROM read_parquet('<your_scratch_dir>/pq_*.parquet') WHERE amount >= 6000;
SELECT count(*) AS n, sum(amount) AS total FROM result;
-- the row groups the filter can rule out without reading them, from the file's own statistics
CREATE TEMP TABLE groups AS
SELECT file_name, row_group_id, max(stats_max_value::DOUBLE) AS max_amount
FROM parquet_metadata('<your_scratch_dir>/pq_*.parquet') WHERE path_in_schema = 'amount' GROUP BY ALL;
SELECT * FROM groups ORDER BY file_name, row_group_id;
SELECT CASE WHEN ((SELECT list(column_name) FROM (DESCRIBE result)) = ['customer', 'amount'] AND (SELECT count(*) = 2193 AND sum(amount) = 15561528 FROM result) AND (SELECT count(*) FROM read_parquet('<your_scratch_dir>/pq_*.parquet')) = 8192 AND (SELECT count(DISTINCT filename) FROM read_parquet('<your_scratch_dir>/pq_*.parquet', filename = true)) = 2 AND (SELECT count(*) = 4 AND count(*) FILTER (WHERE max_amount < 6000) = 2 FROM groups)) THEN 'as expected' ELSE error('the glob did not read 8192 rows from 2 files, the filter did not keep the 2193 orders of 6000 or more, or two of the four row groups were not ruled out by their statistics') END AS verdict;
```

Replace `<your_scratch_dir>` with a directory of your own that you can write to before running the statement.

The statement writes `pq_a.parquet` and `pq_b.parquet` itself, in `<your_scratch_dir>`.

It needs nothing installed beyond DuckDB itself.

## What other tools call it

Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).

- Azure Data Factory: [`Parquet format (source)`](https://learn.microsoft.com/en-us/azure/data-factory/format-parquet) (read 2026-09-27)
- Apache DataFusion: [`Parquet`](https://datafusion.apache.org/user-guide/features.html) (read 2026-09-27)
- DuckDB: `parquet_scan` (read 2026-09-27)
- DuckDB: `read_parquet` (read 2026-09-27)
- Duckle: [`Parquet`](https://github.com/slothflowlabs/duckle/blob/f85f8960edfb6efbf4cb89d58a7b32e16df0e867/website/docs/components.html) (read 2026-09-25)
- EasyMorph: [`Import from Apache Parquet`](https://help.easymorph.com/doku.php?id=transformations:importapacheparquet) (read 2026-09-27)
- AWS Glue: [`Parquet (read)`](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-format-parquet-home.html) (read 2026-09-27)
- Apache Hop: [`Parquet file input`](https://hop.apache.org/manual/latest/pipeline/transforms/parquet-file-input.html) (read 2026-09-27)
- KNIME Analytics Platform: [`KNIME Extension for Big Data File Formats (extension)`](https://api.hub.knime.com/extensions/org.knime.features.bigdata.fileformats) (read 2026-09-27)
- Pentaho Data Integration: [`Parquet Input`](https://docs.pentaho.com/pdia-data-integration/9.3-data-integration/pdi-transformation-steps-reference-overview) (read 2026-09-27)
- Polars: [`read_parquet`](https://docs.pola.rs/api/python/stable/reference/io.html) (read 2026-09-27)
- Polars: [`scan_parquet`](https://docs.pola.rs/api/python/stable/reference/io.html) (read 2026-09-27)
- Power Query M: [`Parquet.Document`](https://learn.microsoft.com/en-us/power-query/connectors/parquet) (read 2026-09-27)
- Talend: [`tFileInputParquet`](https://help.qlik.com/talend/en-US/components/8.0/parquet/parquet-component) (read 2026-09-27)
- Talend: [`tFileStreamInputParquet`](https://help.qlik.com/talend/en-US/components/8.0/parquet/parquet-component) (read 2026-09-27)
- VisiData: [`parquet (loader)`](https://github.com/saulpw/visidata/blob/7609212ec2febafa9caba7183cbebfaf49627909/visidata/loaders/parquet.py#L8) (read 2026-09-23)
