Skip to content

Commit 5cf934d

Browse files
committed
new post: introduction to DuckDB
1 parent 17701fc commit 5cf934d

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed
245 KB
Loading

blog/Introduccion-a-DuckDB.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
---
2+
blogpost: true
3+
date: Feb 10, 2025
4+
author: soloidx
5+
location: Lima, Perú
6+
category: Data science
7+
tags: pandas, python, csv
8+
language: Español
9+
---
10+
11+
# Introducción a DuckDB: Una alternativa ligera y poderosa para análisis de datos
12+
13+
Cuando pensamos en base de datos normalmente se nos ocurre Oracle, PostgreSQL o hasta Redis y MongoDB, pensamos en servidores dentro de arquitecturas con múltiples nodos y clientes que se comunican por la red. Sin embargo no todas las aplicaciones requieren ser tan complejas, tenemos por ejemplo a SQLite, que es ligero y embebido (se integra directamente en la aplicación y no requiere de un servidor) y por eso suele ser la solución perfecta para muchas aplicaciones móviles y web.
14+
15+
![Python developer](/_static/images/introduction_duckdb.png)
16+
17+
Usando SQLite como inspiración nació DuckDB, es una herramienta que, para análisis de datos no requiere de dependencias externas y se ejecuta eficientemente en memoria y es lo suficientemente flexible como para soportar diferentes tipos de datos. En este artículo exploraremos cómo usar DuckDB con Python y por qué puede ser una excelente alternativa para ciertas cargas de trabajo.
18+
19+
## Primeros pasos:
20+
21+
Empezamos instalando DuckDB:
22+
23+
```bash
24+
pip install duckdb
25+
```
26+
27+
Luego dentro de un script o en el REPL iniciamos una instancia:
28+
29+
```python
30+
import duckdb
31+
32+
con = duckdb.connect(database=":memory:", read_only=False)
33+
con.execute("SET temp_directory='/tmp/duckdb.temp';")
34+
```
35+
36+
Aquí:
37+
- Creamos una conexión `con` con la base de datos configurada en memoria.
38+
- Creamos un directorio temporal (en el caso nos quedemos sin memoria)
39+
40+
Ahora obtenemos datos de un archivo CSV con 100 clientes:
41+
42+
```python
43+
customer_100 = con.query("SELECT * FROM read_csv('data/customers-100.csv', normalize_names=TRUE)")
44+
print(customer_100)
45+
```
46+
47+
```text
48+
┌─────────────────┬────────────┬─────────────────────────────────┬───────────────────┐
49+
│ customer_id │ first_name │ company │ city │
50+
│ varchar │ varchar │ varchar │ varchar │
51+
├─────────────────┼────────────┼─────────────────────────────────┼───────────────────┤
52+
│ DD37Cf93aecA6Dc │ Sheryl │ Rasmussen Group │ East Leonard │
53+
│ 1Ef7b82A4CAAD10 │ Preston │ Vega-Gentry │ East Jimmychester │
54+
│ 6F94879bDAfE5a6 │ Roy │ Murillo-Perry │ Isabelborough │
55+
│ 5Cef8BFA16c5e3c │ Linda │ Dominguez, Mcmillan and Donovan │ Bensonview │
56+
│ 053d585Ab6b3159 │ Joanna │ Martin, Lang and Andrade │ West Priscilla │
57+
│ 2d08FB17EE273F4 │ Aimee │ Steele Group │ Chavezborough │
58+
│ EA4d384DfDbBf77 │ Darren │ Lester, Woodard and Mitchell │ Lake Ana │
59+
│ 0e04AFde9f225dE │ Brett │ Sanford, Davenport and Giles │ Kimport │
60+
│ C2dE4dEEc489ae0 │ Sheryl │ Browning-Simon │ Robersonstad │
61+
│ 8C2811a503C7c5a │ Michelle │ Beck-Hendrix │ Elaineberg │
62+
├─────────────────┴────────────┴─────────────────────────────────┴───────────────────┤
63+
│ 10 rows 4 columns │
64+
└────────────────────────────────────────────────────────────────────────────────────┘
65+
```
66+
67+
Eso ha sido sencillo, DuckDB ha sido desarrollado como una herramienta OLAP (procesamiento analítico en línea) por lo que permite analizar múltiples archivos eficientemente aquí podemos ver:
68+
69+
```python
70+
import time
71+
import csv
72+
73+
file_path = 'data/customers-2000000.csv'
74+
75+
start = time.time()
76+
77+
with open(file_path, newline='') as csvfile:
78+
data = list(csv.DictReader(csvfile))
79+
80+
end = time.time()
81+
print(f"CSV read time: {end - start} seconds")
82+
83+
start = time.time()
84+
customer_100 = con.query(f"SELECT * FROM read_csv('{file_path}')")
85+
end = time.time()
86+
87+
print(f"DuckDB read time: {end - start} seconds")
88+
```
89+
90+
Aquí estamos comparando la implementación básica con Python y la de DuckDB, estos son los tiempos:
91+
92+
```text
93+
CSV read time: 5.0357770919799805 seconds
94+
DuckDB read time: 0.061506032943725586 seconds
95+
```
96+
97+
## Integración con Pandas y Pyarrow
98+
99+
DuckDB es flexible al momento de integrarse con otras fuentes de datos como Pandas o Pyarrow
100+
101+
```python
102+
import pandas as pd
103+
from pyarrow import csv
104+
105+
106+
source_path = "data/customers-100.csv"
107+
108+
pd_dataframe = pd.read_csv(source_path)
109+
pa_table = csv.read_csv(source_path)
110+
111+
data = con.query("SELECT * FROM pd_dataframe LIMIT 10;")
112+
print(data)
113+
data = con.query("SELECT * FROM pa_table LIMIT 10;")
114+
print(data)
115+
```
116+
117+
En el código anterior podemos ver que el query toma el nombre de la variable, la conexión toma el valor directamente del scope local e inserta los datos transparentemente.
118+
119+
En otro escenario, si lo que queremos es tomar los datos de DuckDB y ponerlos en un DataFrame de Pandas o Pyarrow podemos hacerlo de esta manera:
120+
121+
```python
122+
customer_100 = con.query("SELECT * FROM read_csv('data/customers-100.csv')")
123+
124+
dataframe = customer_100.df()
125+
126+
pa_table = customer_100.arrow()
127+
128+
print(type(dataframe))
129+
print(type(pa_table))
130+
```
131+
## Integración con la nube
132+
133+
Muchos de los datos que utilizamos no se encuentran almacenados localmente, y para procesarlos tenemos que conectarnos a nubes como AWS, GCP o Azure. Para esto, DuckDB contiene extensiones que podemos instalar y usar para poder conectarnos y hacer consultas directamente desde la nube.
134+
135+
```python
136+
# AWS?
137+
138+
con.execute("INSTALL httpfs;")
139+
con.execute("LOAD httpfs;")
140+
con.execute("INSTALL aws;")
141+
con.execute("LOAD aws;")
142+
con.execute("set http_keep_alive=false;")
143+
con.execute("set s3_endpoint='s3.us-west-2.amazonaws.com';")
144+
con.execute("set s3_region='us-west-2';")
145+
con.execute("CALL load_aws_credentials();")
146+
147+
source = "s3://soloidx-bank1305/apps/balancesheetriskmanagement/output/instrument/data/"
148+
149+
con.query(f"SELECT COUNT(*) FROM read_parquet('{source}**/*.parquet', hive_partitioning = true);")
150+
```
151+
152+
También cabe resaltar que DuckDB maneja eficientemente las consultas sobre directorios, si tenemos un directorio con datos en particiones (como Apache Hive) las consultas se hacen solamente en las particiones definidas en el WHERE dentro del query.
153+
154+
Para terminar, DuckDB es una opción poderosa y ligera para el análisis de datos, ya que no requiere un servidor y se ejecuta eficientemente en memoria. Su rapidez en la lectura y procesamiento de archivos como Parquet, CSV, JSON (y hasta Excel!) lo hace ideal para tareas analíticas sin depender de bases de datos tradicionales. Además, su integración nativa con Pandas y PyArrow y la posibilidad de leer datos de la nube permite a los desarrolladores trabajar con datos de manera fluida dentro de sus flujos de trabajo habituales en Python.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ description = ""
55
authors = ["Ider Delzo <soloidx@gmail.com>", "Jean-Pierre Chauvel <jean.pierre@chauvel.org>"]
66
license = "Apache License, Version 2.0"
77
readme = "README.md"
8+
package-mode = false
89

910
[tool.poetry.dependencies]
1011
python = "^3.12"

0 commit comments

Comments
 (0)