DuckDB (native vs SQLAlchemy)#
Beginning in 0.9, JupySQL supports DuckDB via a native connection and SQLAlchemy, both with comparable performance. JupySQL adds a small overhead; however, this overhead is constant.
At the moment, the only difference is that some features are only available when using SQLAlchemy.
Performance comparison (pandas)#
import pandas as pd
import numpy as np
num_rows = 1_000_000
num_cols = 100
df = pd.DataFrame(np.random.randn(num_rows, num_cols))
Raw DuckDB#
import duckdb
conn = duckdb.connect()
%%timeit
conn.execute("SELECT * FROM df").df()
1.9 s ± 129 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
DuckDB + SQLALchemy#
%load_ext sql
%config SqlMagic.autopandas = True
%config SqlMagic.displaycon = False
%sql duckdb:// --alias duckdb-sqlalchemy
%%timeit
_ = %sql SELECT * FROM df
1.85 s ± 11.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
DuckDB + native#
%sql conn --alias duckdb-native
%%timeit
_ = %sql SELECT * FROM df
1.83 s ± 22.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Performance comparison (polars)#
%config SqlMagic.autopolars = True
%sql duckdb-sqlalchemy
Disabled 'autopandas' since 'autopolars' was enabled.
Switching to connection duckdb-sqlalchemy
Raw DuckDB#
%%timeit
conn.execute("SELECT * FROM df").pl()
1.04 s ± 3.26 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
DuckDB + SQLAlchemy#
%%timeit
_ = %sql SELECT * FROM df
1.06 s ± 4.26 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
DuckDB + native#
%sql duckdb-native
Switching to connection duckdb-native
%%timeit
_ = %sql SELECT * FROM df
1.05 s ± 6.31 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Limitations of using native connections#
As of version 0.9.0, the only caveat is that %sqlcmd
won’t work with a native connection.
%sqlcmd
UsageError: Missing argument for %sqlcmd. Valid commands are: tables, columns, test, profile, explore, snippets