Deletion Vectors en Delta Lake: Funcionamiento interno, impacto en el rendimiento y recomendaciones prácticas
Los Deletion Vectors (DV) son una de las funcionalidades más relevantes en Delta Lake para acelerar las operaciones de modificación de datos.
¿Cómo funcionan los Deletion Vectors?
Tradicionalmente, Delta Lake utiliza un enfoque Copy-on-Write:
cuando se elimina, actualiza o mergea una fila dentro de un archivo Parquet, el archivo completo debe reescribirse, excluyendo las filas afectadas. Esto es costoso en E/S, especialmente para archivos grandes o modificaciones puntuales.
Con los Deletion Vectors, Delta introduce un modelo Merge-on-Read:
Los archivos Parquet originales no se reescriben.
Las filas eliminadas se registran en un archivo auxiliar comprimido (un
.bin).Durante la lectura, el motor aplica el vector de eliminación y descarta esas posiciones lógicamente.
El coste de reescritura total se pospone a operaciones posteriores como
OPTIMIZEoREORG TABLE ... APPLY (PURGE).
Este enfoque reduce de manera drástica la E/S asociada a las operaciones de DELETE/UPDATE/MERGE.
🛠️ Ejemplo Práctico en Microsoft Fabric
A continuación definimos dos tablas Delta:
una sin Deletion Vectors (Copy-on-Write) y otra con DV habilitado (Merge-on-Read).
Preparación y creación de tablas
Primero, creamos los datos base y luego las dos tablas, una sin la propiedad Deletion Vectors y otra con esta propiedad habilitada.
data = [
(1, "Ana", "Ventas"),
(2, "Luis", "IT"),
(3, "Marta", "Marketing"),
(4, "Carlos", "Ventas"),
(5, "Elena", "IT")
]
columns = ["id", "nombre", "departamento"]
df = spark.createDataFrame(data, columns)
# --- Tabla SIN Deletion Vectors (Comportamiento Predeterminado) ---
print("Creando tabla SIN Deletion Vectors...")
df.coalesce(1).write.format("delta").mode("overwrite").saveAsTable("tabla_sin_dv")
# --- Tabla CON Deletion Vectors ---
print("Creando tabla CON Deletion Vectors...")
df.coalesce(1).write.format("delta").mode("overwrite") \
.option("overwriteSchema", "true") \
.option("delta.enableDeletionVectors", "true") \
.saveAsTable("tabla_con_dv")
Puedes verificar la configuración de cada tabla con:
SHOW TBLPROPERTIES tabla_sin_dv;
SHOW TBLPROPERTIES tabla_con_dv;


📂 Comportamiento SIN Deletion Vectors (Copy-on-Write)
Antes del DELETE, la tabla contiene un único Parquet.

Se puede ver que existe un único fichero parquet y un commit en la carpeta _delta_log. Tras ejecutar:
spark.sql(f"DELETE FROM tabla_sin_dv WHERE id = 3")
Delta:
marca el archivo original como
removeen_delta_log,genera un archivo Parquet nuevo con 4 filas,
registra el
addcorrespondiente.

Ejemplo mínimo del commit JSON:
{
...
"operationMetrics": {
"numRemovedFiles": "1",
"numCopiedRows": "4",
"numDeletionVectorsAdded": "0",
"numDeletionVectorsRemoved": "0",
"numAddedChangeFiles": "0",
"numDeletionVectorsUpdated": "0",
"numDeletedRows": "1",
"numAddedFiles": "1",
...
...
}
{
"remove": {
"path": "part-00000-ff53dcfe-e9ee-44c5-ae25-c9e90ba6ff46-c000.snappy.parquet",
"deletionTimestamp": 1764081601227,
...
}
}
{
"add": {
"path": "part-00000-3c93366e-b599-49fe-99e0-f2087490b294-c000.snappy.parquet",
"modificationTime": 1764081601092,
...
}
}
📂 Comportamiento CON Deletion Vectors (Merge-on-Read)
Antes del DELETE, la tabla también tiene un único Parquet.

Se puede ver que también existe un único fichero parquet y un commit en la carpeta _delta_log. Tras ejecutar:
spark.sql(f"DELETE FROM tabla_con_dv WHERE id = 3")
Haciendo el mismo borrado pero para la tabla con Deletion Vectors habilitado, el contenido de la carpeta es el siguiente:
Delta:
mantiene el archivo Parquet tal cual,
añade un archivo
deletion_vector_....bincon la posición invalidada,actualiza el commit indicando el DeletionVector aplicado.

Nuestro nuevo commit contendría lo siguiente, donde se elimina la referencia al archivo Parquet existente y se añade un puntero al mismo archivo Parquet con un vector de eliminación:
{
...
"operationMetrics": {
...
"numRemovedFiles": "0",
"numCopiedRows": "0",
"numDeletionVectorsAdded": "1",
"numDeletionVectorsRemoved": "0",
"numAddedChangeFiles": "0",
"numDeletionVectorsUpdated": "0",
"numDeletedRows": "1",
"numAddedFiles": "0",
...
},
...
}
{
"add": {
"path": "part-00000-67be0c96-23bd-48e4-97a1-c0b43f615ad3-c000.snappy.parquet",
...
"deletionVector": {
"storageType": "u",
"pathOrInlineDv": "5+[vtVR%EkPn{Xs}UU8<",
"offset": 1,
"sizeInBytes": 34,
"cardinality": 1
}
}
}
{
"remove": {
"path": "part-00000-67be0c96-23bd-48e4-97a1-c0b43f615ad3-c000.snappy.parquet",
...
}
}
Resumen de los dos comportamientos
| Tabla | Cambios en archivos | Comportamiento |
tabla_sin_dv | Hay 2 archivos Parquet: el original se marca como eliminado en el Log Delta, y se escribe un archivo Parquet nuevo y más pequeño (el Copy-on-Write). | Se reescribe el archivo afectado. |
tabla_con_dv | Se mantienen los archivos Parquet originales y un nuevo archivo con la extensión .bin (el Deletion Vector). | Se escribe solo el Deletion Vector. El archivo Parquet original NO se reescribe, solo se marca la posición de la fila eliminada. |
📊 Análisis del impacto en rendimiento
Ahora que comprendemos cómo funcionan conceptualmente los vectores de eliminación, veamos el impacto real en el rendimiento.
Para ello, he utilizado un conjunto de datos idéntico de 100 millones de filas en dos tablas Delta diferentes, una con vectores de eliminación habilitados y otra sin. Las pruebas que he realizado para medir el impacto en el rendimiento son:
Borrado de un registro
Borrado del 25% de la tabla
Actualización del 5% de la tabla
MERGE de un nuevo dataset que contiene 2 millones de filas (2%) en la tabla existente
SELECT COUNT(1) WHERE
SELECT SUM()
OPTIMIZE
VACUUM
Las operaciones se han hecho en el mismo orden que aparecen en el listado y los resultados han sido los siguientes:

⏱️ Resultados principales
DELETE (1 fila): La tabla con Deletion Vectors realiza el borrado 6.2x más rápido
DELETE (25M): La tabla con Deletion Vectors realiza el borrado 3.2x más rápido
UPDATE (5M): La tabla con Deletion Vectors realiza el update 3.5x más lento
MERGE (2M): rendimiento similar, ligera penalización con DV
OPTIMIZE: Deletion Vectors es 208x más rápido
VACUUM: Deletion Vectors es 1.6x más rápido
SELECT COUNT(1): DV es 5.9x más lento
SELECT SUM(price): DV es 1.8x más lento
Esto nos lleva a un punto clave:
el beneficio de DV es enorme en escritura, pero las lecturas pueden penalizarse seriamente.
🔍 ¿Por qué las lecturas son más lentas con Deletion Vectors?
La causa no es el DV en sí, sino el modelo Merge-on-Read, donde el lector debe:
Leer los archivos Parquet originales
Leer los vectores de eliminación asociados
Combinar ambas fuentes
Filtrar las filas inválidas
Reconstruir el dataset resultante.
Cuantos más deletes/updates acumula una tabla, más trabajo deben hacer los lectores.
📈 El efecto se amplifica si no se ejecuta OPTIMIZE
En las pruebas:
SELECT COUNT(1) → 5.9x más lento
SELECT SUM() → 1.8x más lento
Esto se debe a que el motor debe leer más datos de los necesarios, incluyendo registros ya invalidados.
🧹 El remedio: compactación
Después de un:
OPTIMIZE <tabla>
o
REORG TABLE <tabla> APPLY (PURGE)
la tabla queda físicamente limpia y las lecturas vuelven a ser rápidas.
🧭 ¿Cuándo habilitar Deletion Vectors?
✔️ Casos recomendados
1. Capas Bronze y Silver
Ideal cuando:
hay ingestas frecuentes
existen deletes/updates parciales
se realizan merges incrementales
la prioridad es la velocidad de ingestión.
2. Workloads MoR donde la E/S es el cuello de botella
DV evita reescrituras costosas en Parquet.
3. Cuando hay una estrategia de optimización establecida
Es imprescindible:
Programar
OPTIMIZEoREORG ... APPLY (PURGE)Ejecutar
VACUUMperiódicamente
❌ Casos NO recomendados
1. Tablas con pocas escrituras y muchas lecturas
Ejemplos:
tablas Gold
modelos de agregación
capas analíticas puras
dashboards con baja latencia
Power BI Direct Lake
Aquí CoW suele ser más eficiente.
2. Problemas de compatibilidad
DV requiere:
Delta Lake 2.3+
Reader version ≥ 3
Writer version ≥ 7
3. Fabric Copy Data Activity (limitación temporal)
Copy Data ignora Deletion Vectors → pueden reaparecer filas “borradas”.
Esto se resolverá (si no se ha resuelto ya) cuando Fabric actualice el soporte a esta funcionalidad.
💡 Conclusión
Los Deletion Vectors representan una innovación clave en Delta Lake que mejora la eficiencia de las operaciones de escritura y reduce la E/S del sistema de forma drástica. Sin embargo, su adopción implica entender claramente las implicaciones del modelo Merge-on-Read, especialmente en términos de rendimiento de lectura.
En escenarios con cargas frecuentes y actualizaciones parciales —especialmente en capas Bronze y Silver— los DV proporcionan mejoras significativas. En contrapartida, en modelos orientados a lectura intensiva como las capas Gold, puede ser preferible mantener el enfoque tradicional Copy-on-Write o aplicar un mantenimiento regular que elimine los vectores acumulados.
En resumen:
DV aceleran la escritura
Penalizan las lecturas si no hay mantenimiento
Ofrecen el mejor rendimiento total cuando se combinan con OPTIMIZE.


