Upřímně? DuckDB je pro mě jedno z nejmilejších překvapení posledních pár let – a v roce 2026 se definitivně prosadilo jako nástroj, bez kterého si lokální analytiku v Pythonu už neumím představit. Datové sady se dnes běžně blíží hranici RAM, uživatelé si (pochopitelně) chtějí zachovat pohodlí Pandas, a DuckDB přesně tenhle prostor zaplňuje: plnohodnotný analytický SQL engine, který běží rovnou v procesu Pythonu. Bez serveru, bez konfigurace, bez zbytečného přesouvání dat.
V tomhle průvodci se podíváme na to, proč DuckDB začíná být výchozí volbou pro lokální analytiku, jak ho propojit s Pandas a Arrow, jak číst Parquet i CSV bez kopírování dat – a hlavně, kdy má smysl klasické Pandas workflow nahradit SQL dotazem. Pojďme na to.
Co je DuckDB a proč ho v roce 2026 používat
DuckDB je vestavěná (in-process) analytická databáze. Chová se podobně jako SQLite, ale je laděná na OLAP úlohy – tedy agregace, okenní funkce, velké JOINy a čtení sloupcových formátů. V Pythonu ho nainstalujete jedním příkazem a hned umí dotazovat Pandas DataFrame, NumPy pole, PyArrow tabulky nebo soubory na disku. Bez explicitního nahrávání dat kamkoli.
Hlavní důvody, proč DuckDB v roce 2026 válcuje tradiční přístupy:
- Sloupcový engine s vektorizovaným zpracováním – výkon srovnatelný s Polars a často o řád lepší než Pandas na agregacích.
- Přímé čtení Parquet a CSV – žádné předzpracování. Soubor se dá dotazovat jako tabulka, včetně glob vzorů a predicate pushdownu.
- Zero-copy integrace s Pandas a Arrow – DataFrame se předává bez kopírování paměti a výsledek se vrací zpět jako
DataFramejediným voláním.df(). - Plné ANSI SQL včetně okenních funkcí, CTE a PIVOT – složité analytické dotazy, které by v Pandas zabraly desítky řádků, zvládnete jako krátký SQL dotaz.
- Práce nad rámec RAM – DuckDB 1.1+ si umí spillovat na disk, takže zvládne i desítky GB na běžném notebooku.
Instalace a rychlý start
Instalace je stejně přímočará jako u jakéhokoli jiného Python balíčku. Rozhodně doporučuji aktuální 1.1+, protože obsahuje nový memory manager a výrazně zrychlenou agregaci (rozdíl oproti 0.10 je na velkých JOINech znát).
pip install --upgrade duckdb pandas pyarrow
A teď minimální příklad, který hezky ukazuje filozofii knihovny – otevřeme in-memory spojení a rovnou pustíme dotaz:
import duckdb
result = duckdb.sql("SELECT 42 AS answer, version() AS duckdb_version").df()
print(result)
Všimněte si, že jsme nic nekonfigurovali. duckdb.sql() si vystačí s výchozím in-memory spojením a .df() vrátí Pandas DataFrame. Pokud potřebujete perzistentní databázi, pak:
con = duckdb.connect("analytics.duckdb")
con.execute("CREATE TABLE IF NOT EXISTS events (id INTEGER, ts TIMESTAMP, amount DOUBLE)")
SQL dotazy přímo nad Pandas DataFrame
A tady přichází to, co mě osobně získalo: DuckDB umí dotazovat existující Pandas DataFrame, jako by to byla obyčejná tabulka. Proměnnou z Pythonu do SQL zpřístupníte jednoduše tím, že na ni odkážete jménem – nic víc.
import duckdb
import pandas as pd
orders = pd.DataFrame({
"order_id": range(1, 7),
"customer": ["Anna", "Petr", "Anna", "Jana", "Petr", "Jana"],
"country": ["CZ", "CZ", "SK", "CZ", "DE", "CZ"],
"amount": [1200.0, 340.5, 890.0, 150.0, 2100.75, 780.0],
})
top = duckdb.sql("""
SELECT customer,
COUNT(*) AS orders,
SUM(amount) AS revenue,
AVG(amount) AS avg_order
FROM orders
WHERE country = 'CZ'
GROUP BY customer
ORDER BY revenue DESC
""").df()
print(top)
Žádná registrace, žádné nahrávání. DuckDB si skrz mechanismus zvaný replacement scan vyzvedne DataFrame přímo z lokálního jmenného prostoru. Výsledek se vrací zpátky do Pandas a vy pokračujete v běžném workflow.
Kdy preferovat SQL místo metod Pandas
Pandas je super pro manipulaci po sloupcích a explorativní analýzu – o tom žádná. DuckDB ale vyniká tam, kde:
- Potřebujete JOIN více DataFrame s komplikovanými podmínkami – v Pandas
merge()bývá hodně ukecané. - Píšete okenní funkce (
ROW_NUMBER(),LAG,RANK) – SQL syntaxe je čitelnější. - Potřebujete PIVOT / UNPIVOT – DuckDB 1.1 má nativní klauzuli
PIVOT. - Chcete reprodukovatelné dotazy, které můžete sdílet s analytiky pracujícími v BI nástrojích.
Čtení Parquet, CSV a JSON bez načítání do paměti
Jedna z věcí, které DuckDB v roce 2026 dělají tak populárním, je schopnost dotazovat datové soubory přímo. Bez toho, že byste je nejdřív museli načíst do DataFrame. Šetří to paměť i čas – DuckDB aplikuje predicate pushdown a čte jen ty sloupce a řádky, které skutečně potřebuje.
import duckdb
# Jeden Parquet soubor
q1 = duckdb.sql("SELECT * FROM 'data/sales_2026.parquet' WHERE amount > 1000")
# Celý adresář přes glob vzor – DuckDB si soubory pospojuje sám
q2 = duckdb.sql("""
SELECT country, SUM(amount) AS revenue
FROM 'data/sales_*.parquet'
GROUP BY country
ORDER BY revenue DESC
""").df()
# CSV s automatickým odvozením typů
q3 = duckdb.sql("SELECT * FROM read_csv_auto('data/customers.csv')").df()
U opravdu velkých CSV souborů doporučuji explicitně nastavit schéma, ať se vyhnete překvapením s odvozením typů (párkrát mě to kouslo, zvlášť když se v datech objevily smíšené formáty dat):
df = duckdb.sql("""
SELECT * FROM read_csv(
'data/events.csv',
header = true,
columns = {
'id': 'BIGINT',
'ts': 'TIMESTAMP',
'user_id': 'VARCHAR',
'value': 'DOUBLE'
}
)
""").df()
Pokročilé analytické dotazy
Pojďme si ukázat, jak DuckDB zjednodušuje úlohy, které by v Pandas znamenaly kombinaci několika kroků. Předpokládejme, že máme DataFrame events s událostmi uživatelů.
Okenní funkce – pořadí nákupu podle zákazníka
ranked = duckdb.sql("""
SELECT
customer_id,
order_id,
order_ts,
amount,
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY order_ts
) AS order_seq,
SUM(amount) OVER (
PARTITION BY customer_id
ORDER BY order_ts
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS lifetime_revenue
FROM orders
""").df()
PIVOT bez manuální transformace
pivoted = duckdb.sql("""
PIVOT orders
ON country
USING SUM(amount)
GROUP BY customer
""").df()
QUALIFY – filtrování po okenní funkci
last_orders = duckdb.sql("""
SELECT *
FROM orders
QUALIFY ROW_NUMBER() OVER (
PARTITION BY customer_id ORDER BY order_ts DESC
) = 1
""").df()
Klauzule QUALIFY je v Pandas celkem oříšek – vyžaduje groupby().tail() nebo ruční filtraci. V DuckDB je to jeden řádek. Tečka.
Integrace s Apache Arrow a Polars
DuckDB od verze 1.0 sdílí paměťový model s Apache Arrow, což umožňuje tzv. zero-copy přenos mezi knihovnami. Pokud už jedete na Arrow tabulkách nebo Polars, můžete DuckDB použít jako SQL vrstvu nad tou samou pamětí.
import duckdb
import polars as pl
import pyarrow as pa
pl_df = pl.read_parquet("data/logs.parquet")
# DuckDB dotazuje Polars DataFrame bez kopírování
arrow_result = duckdb.sql("""
SELECT level, COUNT(*) AS n
FROM pl_df
WHERE ts >= '2026-01-01'
GROUP BY level
""").arrow()
# Výsledek jde převést zpět do Polars bez kopírování
result_pl = pl.from_arrow(arrow_result)
Typický vzor, který v roce 2026 vídám v produkci, je: načíst Parquet přes DuckDB SQL → dostat Arrow tabulku → pokračovat v Polars pro transformace, které se přirozeněji píšou ve výrazech. Každá knihovna dělá to, co umí nejlíp.
Výkonnostní srovnání s Pandas
Na datové sadě NYC Taxi (cca 1,5 miliardy řádků, 25 GB ve sloupcovém formátu Parquet) jsme na laptopu s 32 GB RAM a SSD v březnu 2026 naměřili následující orientační hodnoty pro dotaz, který agreguje průměrné spropitné podle dne v týdnu:
- Pandas 2.2 (data musejí projít
read_parquetdo RAM) – nezvládlo, došla paměť. - Pandas 3.0 s Arrow backendem – 92 s pro 50 GB podmnožinu, kterou se podařilo načíst.
- Polars 1.x lazy – 14 s.
- DuckDB 1.1 přímo nad Parquet – 11 s, a bez nutnosti mít celá data v RAM.
DuckDB navíc automaticky paralelizuje přes všechna jádra CPU a v případě potřeby spillne na disk. Pro jednorázovou lokální analytiku tak dostanete kombinaci výkonu Polars a pohodlí SQL – což je, když se nad tím zamyslíte, poměrně sympatický kompromis.
Od prototypu k ETL pipeline
DuckDB funguje skvěle i jako jádro ETL kroku. Typická pipeline v roce 2026 vypadá zhruba takhle:
- Stáhnout surová data ve formátu CSV/JSON z API nebo objektového úložiště.
- Uložit je do Parquet přes DuckDB – získáte kompresi a sloupcové čtení.
- SQL transformacemi vyrobit datamart ve formátu Parquet pro BI.
import duckdb
con = duckdb.connect()
con.execute("""
COPY (
SELECT
date_trunc('day', ts) AS day,
country,
SUM(amount) AS revenue,
COUNT(*) AS orders
FROM read_json_auto('raw/orders_*.json')
WHERE status = 'paid'
GROUP BY day, country
)
TO 'marts/daily_revenue.parquet' (FORMAT PARQUET, COMPRESSION ZSTD)
""")
Celá pipeline je jeden SQL příkaz. DuckDB zpracuje vstup streamingově, nevyžaduje paměť pro celá data a výstup je rovnou připravený k nasazení do datového skladu nebo BI nástroje jako Metabase či Apache Superset. V jednom projektu jsme takhle nahradili starší pipeline v Airflow a kód se zkrátil zhruba na třetinu.
Nejlepší postupy pro rok 2026
- Ukládejte Parquet se správnou velikostí row group (cca 128 MB) – DuckDB pak může efektivně paralelizovat.
- Používejte explicitní schéma pro kritické CSV soubory – ušetříte si překvapení s odvozením typů.
- Pro opakované dotazy si založte perzistentní databázi – DuckDB si uloží statistiky a optimalizuje plán.
- Preferujte
.arrow()před.df(), pokud následně jedete na Polars nebo PyArrow – ušetříte si konverzi. - Nepřenášejte DuckDB spojení mezi vlákny bez
con.cursor()– každé vlákno potřebuje vlastní kurzor. - V Jupyter notebooku využijte
%load_ext sqls adaptéremduckdb-enginea získáte magic příkazy%%sql.
DuckDB vs Polars vs Pandas: kdy co
V produkci se tyhle tři nástroje vzájemně doplňují a v roce 2026 už vážně nejde o situaci „buď, anebo":
- Pandas – interaktivní explorace malých a středních dat, kompatibilita s ekosystémem (matplotlib, scikit-learn).
- Polars – deklarativní transformace ve výrazech, lazy evaluace pro pipeline.
- DuckDB – analytické SQL dotazy, JOINy, přímé čtení Parquet, ETL transformace, reporting.
Typický moderní workflow, který vídám nejčastěji: DuckDB pro ingest a těžkou agregaci → Arrow jako výměnný formát → Polars nebo Pandas pro finální úpravy → matplotlib/Plotly pro vizualizaci.
Časté otázky (FAQ)
Je DuckDB zdarma a open source?
Ano. DuckDB je vyvíjen jako open-source projekt pod MIT licencí, takže ho můžete použít komerčně i v uzavřených produktech bez omezení. Hlavními sponzory jsou DuckDB Labs a MotherDuck (ti nabízejí placenou cloudovou verzi), samotná knihovna ale zůstává zdarma.
Nahradí DuckDB Pandas?
Nenahradí. DuckDB a Pandas řeší jiné třídy problémů – DuckDB je silný v analytických SQL dotazech a práci s velkými datovými soubory, Pandas je zase nenahraditelné pro interaktivní manipulaci s menšími DataFrame a pro integraci se scikit-learn, matplotlibem nebo statsmodels. V roce 2026 je běžné používat obě knihovny vedle sebe.
Zvládne DuckDB data, která se nevejdou do RAM?
Ano. DuckDB 1.1 a novější automaticky spillují mezivýsledky na disk, pokud dotaz překročí dostupnou paměť. V praxi jsme viděli zpracování 50–100 GB Parquet dat na notebooku s „pouhými" 16 GB RAM.
Jak DuckDB pracuje s Pandas DataFrame interně?
DuckDB používá tzv. replacement scan – když v SQL zmíníte název proměnné, která obsahuje Pandas DataFrame, DuckDB ji rozpozná v lokálním jmenném prostoru a přečte její sloupcovou reprezentaci přímo z paměti. U DataFrame s Arrow backendem je přenos zero-copy, u klasického NumPy DataFrame proběhne rychlá konverze sloupců.
Je DuckDB vhodné pro produkční použití?
Ano. DuckDB dosáhlo stabilní verze 1.0 v roce 2024 a od té doby se v produkci používá pro lokální analytiku, embedded databáze v desktopových aplikacích, serverless datové pipeline a jako engine pod BI nástroji. Pro OLTP workload (hodně malých transakčních zápisů) ale pořád volte spíš PostgreSQL nebo SQLite – na tohle DuckDB dělané není.
Závěr
DuckDB v roce 2026 posunulo laťku pro lokální analytiku v Pythonu hodně nahoru. Nabízí výkon sloupcových databází, pohodlí SQL a těsnou integraci s Pandas, Polars i Arrow – a to všechno bez nutnosti provozovat server. Pokud doteď řešíte agregace nad stovkami tisíc řádků v Pandas a narážíte na paměť nebo výkon, zkuste ten samý dotaz přepsat do SQL nad DuckDB. Ve většině případů dostanete kratší kód, výrazně nižší paměťovou stopu a čas zpracování v řádu sekund místo minut. Z mé zkušenosti je to jedno z mála rozhodnutí, u kterého budete lítostí, že jste nezačali dřív.