(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo crear particiones dinámicas en tablas Delta en el Lakehouse

João Barros 09 de October de 2026 6 min de lectura

Este tutorial muestra cómo crear particiones dinámicas en una tabla Delta en el Lakehouse para mejorar la lectura y escritura de datos. Particionar correctamente reduce costes de I/O, acelera consultas y evita archivos pequeños cuando se escribe en paralelo. Además, particiones bien definidas facilitan operaciones de limpieza y retención y ayudan al motor a aplicar partition pruning, lo que puede reducir el volumen leído entre 10x y 100x en escenarios comunes.

Requisitos previos

  • Cuenta con acceso a Microsoft Fabric y un Lakehouse creado.
  • Permisos para crear/alterar tablas Delta en el Lakehouse.
  • Archivos de ejemplo (CSV/JSON) cargados en un path del Lakehouse o OneLake.
  • Conocimientos básicos de SQL y PySpark.

Paso 1: Elegir la columna de partición correcta

Por qué: una buena columna de partición equilibra el número de archivos y la selectividad de las consultas. Evite columnas con alta cardinalidad (p. ej.: ID único con millones de valores) — eso crea muchas particiones pequeñas y aumenta la sobrecarga de metadatos. Tampoco use columnas con cardinalidad muy baja (p. ej.: un campo con siempre el mismo valor), porque ahí no hay beneficio. Para datos temporales, usar una jerarquía como year/month[/day] es una práctica común. Por ejemplo:

  • Fechas: year/month — buen equilibrio para años con ~12 meses y cientos de miles a millones de registros por mes.
  • Alta cardinalidad: user_id con 10M de usuarios — no usar como partición.
  • Baja cardinalidad: country con 5-10 valores — no suficiente para reducción significativa de I/O.

Regla práctica: cada partición debe contener al menos decenas de MB a cientos de MB (p. ej.: 100-500 MB) para ser eficiente con archivos Delta. Si sus particiones quedan consistentemente por debajo de ~64 MB, considere reducir la granularidad de las particiones.

Paso 2: Crear una tabla Delta no particionada (opcional, para importar datos iniciales)

Es útil empezar sin partición para validar esquema y luego convertir a particionada cuando tenga carga de datos real. Esto ayuda a verificar tipos y nulos con datos reales antes de definir particiones definitivas. Ejemplo en SQL en el SQL Analytics endpoint o notebook:

CREATE TABLE IF NOT EXISTS my_db.raw_events_delta
USING DELTA
LOCATION 'lakehouse:////raw/events'
AS SELECT * FROM csv.`/paths/events/*.csv`;

Después de importar algunos millones de filas, inspeccione muestras y observe la distribución temporal para decidir si usa year/month/day.

Paso 3: Crear tabla Delta particionada con esquema final

Crée la tabla con PARTITIONED BY. Aquí usamos year y month extraídos de la columna event_timestamp. Esto crea una estructura de carpetas organizada, por ejemplo /year=2024/month=06/, que facilita el pruning y la gestión de datos.

CREATE TABLE IF NOT EXISTS my_db.events_delta
(
  event_id STRING,
  event_timestamp TIMESTAMP,
  user_id STRING,
  event_type STRING,
  payload STRING
)
USING DELTA
PARTITIONED BY (year, month)
LOCATION 'lakehouse:////tables/events';

Nota: elegir PARTITIONED BY evita la necesidad de crear columnas físicas separadas para year y month si prefiere extraerlas en el SELECT, pero tener columnas explícitas facilita las consultas y los índices.

Paso 4: Escribir datos usando particiones dinámicas con PySpark

Al escribir, calcule year y month y use write.partitionBy para crear particiones dinámicas. Esto garantiza que los archivos se escriben en la carpeta correcta según la fecha del evento. Ejemplo PySpark mínimo:

from pyspark.sql.functions import year, month, to_timestamp

df = spark.read.csv('/mnt/lake/events/*.csv', header=True)
df = df.withColumn('event_timestamp', to_timestamp(df.event_timestamp))
df = df.withColumn('year', year(df.event_timestamp))
df = df.withColumn('month', month(df.event_timestamp))

(df.write
  .format('delta')
  .mode('append')
  .partitionBy('year','month')
  .save('lakehouse:////tables/events'))

Ejemplo concreto: si tiene 10M de registros por mes y un cluster con 200 ejecutores, estime los archivos finales por partición y ajuste repartition para alcanzar ~128 MB por archivo.

Paso 5: Evitar archivos pequeños (small files) al escribir en paralelo

Error común: cada ejecutor escribe pocos MB, creando cientos de archivos pequeños por partición, lo que degrada el rendimiento. Soluciones:

  • Aumentar el tamaño de los archivos con coalesce/repartition antes de escribir: por ejemplo, si pretende archivos ~128 MB y tiene 1 TB de datos, estime 8000 archivos y haga repartition(8000).
  • Reparticionar por una clave de partición lógica (p. ej.: concat year-month) para agrupar datos de la misma partición antes del write.
  • Ejecutar OPTIMIZE / compaction después de la ingestión para combinar archivos pequeños (cuando esté soportado en el entorno).
# Reparticionar por partición aproximada antes de escribir
from pyspark.sql.functions import concat_ws

# Crear una columna de partition_key para reparticionar
df = df.withColumn('partition_key', concat_ws('-', df.year.cast('string'), df.month.cast('string')))
# Repartition por partition_key para reducir archivos
df = df.repartition('partition_key')

(df.drop('partition_key')
  .write
  .format('delta')
  .mode('append')
  .partitionBy('year','month')
  .save('lakehouse:////tables/events'))

Paso 6: Actualizar esquema o añadir particiones

Si añade nuevas columnas, use ALTER TABLE para evitar reescribir toda la tabla. Para detectar nuevas carpetas/particiones externas, algunos entornos soportan comandos como MSCK REPAIR; otros ofrecen SHOW PARTITIONS. Ejemplos:

ALTER TABLE my_db.events_delta ADD COLUMNS (device STRING);
-- Listar particiones
SHOW PARTITIONS my_db.events_delta;

Si es necesario migrar de no particionado a particionado con millones de filas, haga una escritura controlada en batch para evitar picos de I/O.

Verificar el resultado

Confirme que las particiones existen y que las consultas realizan partition pruning. Ejecute:

-- Ver particiones físicas
SHOW PARTITIONS my_db.events_delta;

-- Prueba de partition pruning (verifica planes)
EXPLAIN SELECT * FROM my_db.events_delta WHERE year = 2024 AND month = 6;

-- Contar por partición
SELECT year, month, COUNT(*) FROM my_db.events_delta GROUP BY year, month ORDER BY year, month;

Si EXPLAIN muestra que solo se leen las rutas year=2024/month=6, el pruning está funcionando. Monitorice tiempos de consulta y I/O: idealmente verá una reducción significativa cuando el filtro coincida con particiones.

Conclusión

Las particiones dinámicas en tablas Delta en el Lakehouse mejoran el rendimiento y el coste cuando están bien elegidas. Empiece con una granularidad conservadora (year/month), monitorice la distribución de datos y el tamaño medio de los archivos y ajuste repartition al escribir. Próximos pasos: automatizar la partición en pipelines de ingestión, usar OPTIMIZE y ZORDER (cuando esté soportado) para mejorar el ordenamiento interno y reducir la latencia de lectura, y crear alertas para detectar crecimiento de archivos pequeños. Consejo práctico: apunte a archivos de ~128–256 MB por partición y revise la estrategia cada trimestre según el crecimiento de los datos.