Parallel Execution
Learning Focus
Use this lesson to understand DuckDB's parallel execution model and how to tune it for your hardware.
DuckDB is Parallel by Default
DuckDB automatically uses all available CPU cores to parallelize queries. There is no configuration needed for basic parallel execution.
-- This query automatically runs in parallel on all cores
SELECT department, SUM(salary)
FROM read_parquet('huge_employees.parquet')
GROUP BY department;
How DuckDB Parallelizes
Query → Split into pipelines → Each pipeline runs in parallel threads
┌────────────────────────────────────────────┐
│ Thread 1: scan rows 0-1M │
│ Thread 2: scan rows 1M-2M │
│ Thread 3: scan rows 2M-3M │
│ Thread 4: scan rows 3M-4M │
└────────────────────────────────────────────┘
↓
Merge + Aggregate
Configuring Thread Count
-- Check current thread count
PRAGMA threads;
-- Set to specific count (default: all logical cores)
PRAGMA threads = 4;
-- Restore to auto (use all cores)
PRAGMA threads = -1;
-- Via environment
-- DUCKDB_NO_THREADS=4 duckdb mydb.db
Memory Configuration
-- Check memory limit
PRAGMA memory_limit;
-- Set memory limit
PRAGMA memory_limit = '8GB';
-- Set temp directory for spill-to-disk
PRAGMA temp_directory = '/tmp/duckdb_temp';
Monitoring Query Parallelism
-- View active queries and thread usage (DuckDB Progress Bar)
PRAGMA enable_progress_bar;
-- Check query pipeline info via EXPLAIN
EXPLAIN ANALYZE
SELECT COUNT(*), AVG(salary)
FROM read_parquet('huge_dataset.parquet');
Parallel File Reads
-- Multiple Parquet files are read in parallel automatically
SELECT * FROM read_parquet('data/*.parquet');
-- S3 files are also read in parallel
LOAD httpfs;
SELECT * FROM read_parquet('s3://bucket/events/**/*.parquet');
Vectorized Execution
DuckDB processes data in vectors of 1024 rows rather than row-by-row. This:
- Maximizes CPU cache efficiency
- Enables SIMD instructions
- Reduces function call overhead
You do not need to configure vectorized execution — it is always active.
Benchmarking Parallel Queries
-- Enable timing
.timer on
-- Single thread
PRAGMA threads = 1;
SELECT COUNT(*), AVG(salary) FROM read_parquet('data.parquet');
-- All cores
PRAGMA threads = -1;
SELECT COUNT(*), AVG(salary) FROM read_parquet('data.parquet');
Common Pitfalls
| Pitfall | Consequence | Prevention |
|---|---|---|
| Using DuckDB in many concurrent processes | Memory contention | DuckDB works best with one process; use one connection |
| Setting too many threads on a shared server | Starves other processes | Set PRAGMA threads = N where N is your allocated core count |
| Running DuckDB in Docker with limited CPUs | Reduced parallelism | Set --cpus Docker flag appropriately |
Quick Reference
PRAGMA threads; -- show current
PRAGMA threads = 8; -- set to 8 cores
PRAGMA memory_limit = '4GB';
PRAGMA temp_directory = '/tmp/duck_spill';
PRAGMA enable_progress_bar;
EXPLAIN ANALYZE query;
What's Next
- Next: Database Management - Manage DuckDB files, schemas, and exports.
- Module Overview - Return to this module index.