Exporting with COPY

DuckDB · Practical · 10 min

Converting and exporting data is half of every pipeline, and DuckDB does it in one statement.

COPY ... TO writes a table or the result of any query to a file:

COPY (SELECT * FROM events WHERE ok) TO 'events.parquet' (FORMAT parquet);

The format is inferred from the extension, or set with FORMAT. Useful options:

  • Parquet: COMPRESSION zstd (the default is snappy), ROW_GROUP_SIZE
  • CSV: HEADER, DELIMITER
  • PARTITION_BY (col, ...) writes a Hive-style folder tree, one subfolder per value
  • OVERWRITE_OR_IGNORE / OVERWRITE control what happens if the target folder exists
  • PER_THREAD_OUTPUT writes one file per thread for maximum speed

The reverse direction, COPY tbl FROM 'file.csv', appends a file into an existing table, though INSERT INTO tbl SELECT * FROM 'file.csv' is more flexible.

A common one-liner is CSV to Parquet conversion: COPY (FROM 'raw.csv') TO 'clean.parquet'. To move an entire database, EXPORT DATABASE 'dir' writes every table plus a schema script, and IMPORT DATABASE 'dir' rebuilds it.

Sort data by a frequently filtered column before writing Parquet: row-group min/max statistics then become tight, and later filters skip far more data.

Example

import duckdb, os, tempfile

os.chdir(tempfile.mkdtemp())
con = duckdb.connect()
con.sql("CREATE TABLE t AS SELECT i AS id, 'item' || i AS name FROM range(5) r(i)")

con.sql("COPY t TO 'items.csv' (HEADER, DELIMITER ',')")
con.sql("COPY (SELECT * FROM t WHERE id >= 3 ORDER BY id) TO 'items.parquet' "
        "(FORMAT parquet, COMPRESSION zstd)")

print(open("items.csv").read().splitlines()[:2])   # ['id,name', '0,item0']
print(con.sql("FROM 'items.parquet'").fetchall())  # [(3, 'item3'), (4, 'item4')]

Remember

  • COPY (query) TO 'file' exports any result; format follows the extension or FORMAT
  • PARTITION_BY writes Hive-partitioned folders
  • Sorting before writing Parquet makes later filtering much faster

Watch out for

  • Writing a partitioned export twice into the same folder without OVERWRITE options and getting an error or duplicate files.

Check yourself

  1. What is the simplest way to convert raw.csv into Parquet with DuckDB?

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

Official docs: duckdb.org/docs/current/sql/statements/copy

Builds on

Unlocks

Nothing builds on this yet.