Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Las tablas admiten la evolución del esquema, lo que permite modificaciones en la estructura de tablas a medida que cambian los requisitos de datos. Se admiten los siguientes tipos de cambios:
- Adición de nuevas columnas en posiciones arbitrarias
- Reordenación de las columnas existentes
- Cambio de nombre de las columnas existentes
Realice estos cambios explícitamente mediante DDL o implícitamente mediante DML.
Importante
Las actualizaciones de esquema entran en conflicto con todas las operaciones de escritura simultáneas. Databricks recomienda coordinar los cambios de esquema para evitar conflictos de escritura.
La actualización de un esquema de tabla finaliza las secuencias que se leen desde esa tabla. Para continuar con el procesamiento, reinicie la secuencia mediante los métodos descritos en Consideraciones de producción para Structured Streaming.
Actualizar explícitamente el esquema para agregar columnas
ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)
De manera predeterminada, la nulabilidad es true.
Para agregar una columna a un campo anidado, use:
ALTER TABLE table_name ADD COLUMNS (col_name.nested_col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)
Por ejemplo, si el esquema antes de ejecutarse ALTER TABLE boxes ADD COLUMNS (colB.nested STRING AFTER field1) es:
- root
| - colA
| - colB
| +-field1
| +-field2
El esquema después es:
- root
| - colA
| - colB
| +-field1
| +-nested
| +-field2
Nota:
La adición de columnas anidadas solo se admite para los structs. No se admiten matrices ni mapas.
Actualizar explícitamente el esquema para cambiar el comentario o la ordenación de columnas
ALTER TABLE table_name ALTER [COLUMN] col_name (COMMENT col_comment | FIRST | AFTER colA_name)
Para cambiar una columna en un campo anidado, use:
ALTER TABLE table_name ALTER [COLUMN] col_name.nested_col_name (COMMENT col_comment | FIRST | AFTER colA_name)
Por ejemplo, si el esquema antes de ejecutarse ALTER TABLE boxes ALTER COLUMN colB.field2 FIRST es:
- root
| - colA
| - colB
| +-field1
| +-field2
El esquema después es:
- root
| - colA
| - colB
| +-field2
| +-field1
Actualizar explícitamente el esquema para reemplazar columnas
ALTER TABLE table_name REPLACE COLUMNS (col_name1 col_type1 [COMMENT col_comment1], ...)
Por ejemplo, al ejecutar el siguiente DDL:
ALTER TABLE boxes REPLACE COLUMNS (colC STRING, colB STRUCT<field2:STRING, nested:STRING, field1:STRING>, colA STRING)
Si el esquema antes es:
- root
| - colA
| - colB
| +-field1
| +-field2
El esquema después es:
- root
| - colC
| - colB
| +-field2
| +-nested
| +-field1
| - colA
Actualizar explícitamente el esquema para cambiar el nombre de las columnas
Nota:
Esta característica está disponible en Databricks Runtime 10.4 LTS y versiones posteriores.
Para cambiar el nombre de las columnas sin volver a escribir ninguno de los datos existentes de las columnas, debe habilitar la asignación de columnas para la tabla. Consulte Cambio de nombre y eliminación de columnas con la asignación de columnas de Delta Lake.
Para cambiar el nombre de una columna:
ALTER TABLE table_name RENAME COLUMN old_col_name TO new_col_name
Para cambiar el nombre de un campo anidado:
ALTER TABLE table_name RENAME COLUMN col_name.old_nested_field TO new_nested_field
Por ejemplo, cuando ejecute el siguiente comando:
ALTER TABLE boxes RENAME COLUMN colB.field1 TO field001
Si el esquema antes es:
- root
| - colA
| - colB
| +-field1
| +-field2
El esquema después es:
- root
| - colA
| - colB
| +-field001
| +-field2
Consulte Renombrar y eliminar columnas con mapeo de columnas de Delta Lake.
Actualizar explícitamente el esquema para quitar columnas
Nota:
Esta característica está disponible en Databricks Runtime 11.3 LTS y versiones posteriores.
Para eliminar columnas como una operación de solo metadatos sin volver a escribir ningún archivo de datos, debe habilitar la asignación de columnas para la tabla. Consulte Renombrar y eliminar columnas con asignación de columnas en Delta Lake.
Importante
La eliminación de una columna de los metadatos no elimina los datos subyacentes de la columna en los archivos. Para purgar los datos de la columna eliminada, puede usar REORG TABLE para reescribir los archivos. Después, puede usar VACUUM para eliminar físicamente los archivos que contienen los datos de la columna eliminada.
Para eliminar una columna:
ALTER TABLE table_name DROP COLUMN col_name
Para eliminar varias columnas:
ALTER TABLE table_name DROP COLUMNS (col_name_1, col_name_2)
Actualizar explícitamente el esquema para cambiar el tipo o el nombre de columna
Puede cambiar el tipo o el nombre de una columna o quitar una columna reescribiendo la tabla. Para ello, use la opción overwriteSchema.
En el ejemplo siguiente se muestra cómo cambiar un tipo de columna:
(spark.read.table(...)
.withColumn("birthDate", col("birthDate").cast("date"))
.write
.mode("overwrite")
.option("overwriteSchema", "true")
.saveAsTable(...)
)
En el ejemplo siguiente se muestra cómo cambiar un nombre de columna:
(spark.read.table(...)
.withColumnRenamed("dateOfBirth", "birthDate")
.write
.mode("overwrite")
.option("overwriteSchema", "true")
.saveAsTable(...)
)
Habilitación de la evolución del esquema
Habilite la evolución del esquema mediante uno de los métodos siguientes:
-
Establezca la
mergeSchemaopción: Funciona conINSERT, escrituras por lotes o escrituras de streaming. Establézcalo.option("mergeSchema", "true")en operaciones individuales de escritura. -
Usar
MERGE WITH SCHEMA EVOLUTIONsintaxis: funciona conMERGEinstrucciones . IncluyaWITH SCHEMA EVOLUTIONen la sintaxis SQL o use.withSchemaEvolution()en la API de Azure Databricks. -
Establezca la configuración de Spark (heredada): Establece
spark.databricks.delta.schema.autoMerge.enabledentruepara toda SparkSession. No se recomienda para su uso en producción.
Databricks recomienda habilitar la evolución del esquema para cada operación de escritura mediante la mergeSchema opción o WITH SCHEMA EVOLUTION sintaxis en lugar de establecer una configuración de Spark.
Cuando se usan opciones o sintaxis para habilitar la evolución del esquema en una operación de escritura, esto tiene prioridad sobre la configuración de Spark.
Nota:
No hay ninguna WITH SCHEMA EVOLUTION cláusula para las INSERT INTO instrucciones. Use la mergeSchema opción en su lugar. Consulte Habilitar la evolución del esquema para las escrituras para agregar nuevas columnas.
Habilitar la evolución del esquema al escribir para agregar nuevas columnas
Las columnas que están presentes en la consulta de origen pero que faltan en la tabla objetivo se agregan automáticamente como parte de una transacción de escritura cuando la evolución del esquema está habilitada. Consulte Habilitación de la evolución del esquema.
Las mayúsculas y minúsculas se conservan al anexar una nueva columna. Las nuevas columnas se añaden al final del esquema de la tabla. Si las columnas adicionales están en una estructura, se anexan al final de la estructura de la tabla de destino.
Nota:
A diferencia de las instrucciones que admiten la WITH SCHEMA EVOLUTION sintaxis SQL, las INSERT usan la opción para habilitar la mergeSchema evolución del esquema. No hay ninguna WITH SCHEMA EVOLUTION cláusula para las INSERT INTO instrucciones.
INSERT con la evolución del esquema mediante DataFrame API
En el ejemplo siguiente se muestra cómo usar la opción mergeSchema con una operación de escritura por lotes:
Pitón
(spark.read
.table("source_table")
.write
.option("mergeSchema", "true")
.mode("append")
.saveAsTable("target_table")
)
Scala
spark.read
.table("source_table")
.write
.option("mergeSchema", "true")
.mode("append")
.saveAsTable("target_table")
INSERT con la evolución del esquema en streaming
En el siguiente ejemplo se muestra cómo usar la opción mergeSchema con Auto Loader. Consulte ¿Qué es Auto Loader?.
(spark.readStream
.format("cloudFiles")
.option("cloudFiles.format", "json")
.option("cloudFiles.schemaLocation", "<path-to-schema-location>")
.load("<path-to-source-data>")
.writeStream
.option("mergeSchema", "true")
.option("checkpointLocation", "<path-to-checkpoint>")
.trigger(availableNow=True)
.toTable("table_name")
)
Evolución automática del esquema para la combinación
La evolución del esquema permite resolver los errores de coincidencia de esquema entre la tabla de destino y de origen en la fusión. Controla los dos casos siguientes:
Existe una columna en la tabla de origen, pero no en la tabla de destino, y se especifica por nombre en una asignación de acciones de inserción o actualización. Como alternativa, una acción
UPDATE SET *oINSERT *está presente.Esa columna se agregará al esquema de destino y sus valores se rellenarán desde la columna correspondiente del origen.
Esto solo se aplica cuando el nombre de columna y la estructura del origen de combinación coinciden exactamente con la asignación de destino.
La nueva columna debe estar presente en el esquema de origen. La asignación de la nueva columna en la cláusula de acción no define esa columna.
Estos ejemplos permiten la evolución del esquema:
-- The column newcol is present in the source but not in the target. It will be added to the target. UPDATE SET target.newcol = source.newcol -- The field newfield doesn't exist in struct column somestruct of the target. It will be added to that struct column. UPDATE SET target.somestruct.newfield = source.somestruct.newfield -- The column newcol is present in the source but not in the target. -- It will be added to the target. UPDATE SET target.newcol = source.newcol + 1 -- Any columns and nested fields in the source that don't exist in target will be added to the target. UPDATE SET * INSERT *Estos ejemplos no desencadenan la evolución del esquema si la columna
newcolno está presente en elsourceesquema:UPDATE SET target.newcol = source.someothercol UPDATE SET target.newcol = source.x + source.y UPDATE SET target.newcol = source.output.newcolExiste una columna en la tabla de destino, pero no en la tabla de origen.
No se cambia el esquema de destino. Estas columnas:
Se dejan sin cambios para
UPDATE SET *.Se establecen en
NULLparaINSERT *.Puede modificarse explícitamente si se asigna en la cláusula de acción.
Por ejemplo:
UPDATE SET * -- The target columns that are not in the source are left unchanged. INSERT * -- The target columns that are not in the source are set to NULL. UPDATE SET target.onlyintarget = 5 -- The target column is explicitly updated. UPDATE SET target.onlyintarget = source.someothercol -- The target column is explicitly updated from some other source column.
Debe habilitar manualmente la evolución automática del esquema. Consulte Habilitación de la evolución del esquema.
Nota:
En Databricks Runtime 12.2 LTS y versiones posteriores, los campos de estructura y columnas presentes en la tabla de origen se pueden especificar por nombre en las acciones de inserción o actualización. En Databricks Runtime 11.3 LTS y versiones posteriores, solo se pueden usar acciones INSERT * o UPDATE SET * para la evolución del esquema con combinación.
En Databricks Runtime 13.3 LTS y versiones posteriores, puede usar la evolución del esquema con estructuras anidadas dentro de mapas, como map<int, struct<a: int, b: int>>.
Sintaxis de evolución del esquema para combinación
En Databricks Runtime 15.4 LTS y versiones posteriores, puede especificar la evolución del esquema en una instrucción merge mediante SQL o las API de tabla:
SQL
MERGE WITH SCHEMA EVOLUTION INTO target
USING source
ON source.key = target.key
WHEN MATCHED THEN
UPDATE SET *
WHEN NOT MATCHED THEN
INSERT *
WHEN NOT MATCHED BY SOURCE THEN
DELETE
Pitón
from delta.tables import *
(targetTable
.merge(sourceDF, "source.key = target.key")
.withSchemaEvolution()
.whenMatchedUpdateAll()
.whenNotMatchedInsertAll()
.whenNotMatchedBySourceDelete()
.execute()
)
Scala
import io.delta.tables._
targetTable
.merge(sourceDF, "source.key = target.key")
.withSchemaEvolution()
.whenMatched()
.updateAll()
.whenNotMatched()
.insertAll()
.whenNotMatchedBySource()
.delete()
.execute()
Operaciones de ejemplo de fusión con evolución del esquema
Estos son algunos ejemplos de los efectos de la operación merge con y sin evolución del esquema.
| Columnas | Consulta (en SQL) | Comportamiento sin evolución del esquema (valor predeterminado) | Comportamiento con evolución del esquema |
|---|---|---|---|
Columnas de destino: key, valueColumnas de origen: key, value, new_value |
MERGE INTO target_table tUSING source_table sON t.key = s.keyWHEN MATCHED THEN UPDATE SET *WHEN NOT MATCHED THEN INSERT * |
El esquema de tabla permanece sin cambios; solo se actualizan o insertan las columnas key y value. |
El esquema de tabla se cambia a (key, value, new_value). Los registros existentes con coincidencias se actualizan con value y new_value en el origen. Las filas nuevas se insertan con el esquema (key, value, new_value). |
Columnas de destino: key, old_valueColumnas de origen: key, new_value |
MERGE INTO target_table tUSING source_table sON t.key = s.keyWHEN MATCHED THEN UPDATE SET *WHEN NOT MATCHED THEN INSERT * |
Las acciones UPDATE y INSERT inician un error porque la columna de destino old_value no está en el origen. |
El esquema de tabla se cambia a (key, old_value, new_value). Los registros existentes con coincidencias se actualizan utilizando new_value del origen y se deja old_value sin modificar. Los nuevos registros se insertan con los valores key, new_value y NULL especificados para old_value. |
Columnas de destino: key, old_valueColumnas de origen: key, new_value |
MERGE INTO target_table tUSING source_table sON t.key = s.keyWHEN MATCHED THEN UPDATE SET new_value = s.new_value |
UPDATE genera un error porque la columna new_value no existe en la tabla de destino. |
El esquema de tabla se cambia a (key, old_value, new_value). Los registros existentes con coincidencias se actualizan con new_value en el origen y se deja old_value sin cambios. En los registros no coincidentes se especifica NULL para new_value. Consulte la nota (1). |
Columnas de destino: key, old_valueColumnas de origen: key, new_value |
MERGE INTO target_table tUSING source_table sON t.key = s.keyWHEN NOT MATCHED THEN INSERT (key, new_value) VALUES (s.key, s.new_value) |
INSERT genera un error porque la columna new_value no existe en la tabla de destino. |
El esquema de tabla se cambia a (key, old_value, new_value). Los nuevos registros se insertan con los valores key, new_value y NULL especificados para old_value. En los registros existentes se especifica NULL para new_value y se deja old_value sin cambios. Consulte la nota (1). |
(1) Este comportamiento está disponible en Databricks Runtime 12.2 LTS y versiones posteriores; Databricks Runtime 11.3 LTS y versiones anteriores producen un error en esta condición.
Excluir columnas que participan en una combinación
En Databricks Runtime 12.2 LTS y versiones posteriores, puede usar cláusulas EXCEPT en condiciones de combinación para excluir explícitamente columnas. El comportamiento de la palabra clave EXCEPT varía en función de si está habilitada o no la evolución del esquema.
Con la evolución del esquema deshabilitada, la palabra clave EXCEPT se aplica a la lista de columnas de la tabla de destino y permite excluir columnas de acciones UPDATE o INSERT. Las columnas excluidas se establecen en null.
Con la evolución del esquema habilitada, la palabra clave EXCEPT se aplica a la lista de columnas de la tabla de origen y permite excluir columnas de la evolución del esquema. Una nueva columna del origen que no está presente en el destino no se agrega al esquema de destino si aparece en la cláusula EXCEPT. Las columnas excluidas que ya están en el destino se configuran como null.
En los ejemplos siguientes se muestra esta sintaxis:
| Columnas | Consulta (en SQL) | Comportamiento sin evolución del esquema (valor predeterminado) | Comportamiento con evolución del esquema |
|---|---|---|---|
Columnas de destino: id, title, last_updatedColumnas de origen: id, title, review, last_updated |
MERGE INTO target tUSING source sON t.id = s.idWHEN MATCHED THEN UPDATE SET last_updated = current_date()WHEN NOT MATCHED THEN INSERT * EXCEPT (last_updated) |
Las filas coincidentes se actualizan estableciendo el campo last_updated en la fecha actual. Las filas nuevas se insertan mediante valores de id y title. El campo last_updated excluido se establece en null. El campo review se omite porque no está en el destino. |
Las filas coincidentes se actualizan estableciendo el campo last_updated en la fecha actual. El esquema ha evolucionado para agregar el campo review. Las filas nuevas se insertan con todos los campos de origen, excepto last_updated que se establece en null. |
Columnas de destino: id, title, last_updatedColumnas de origen: id, title, review, internal_count |
MERGE INTO target tUSING source sON t.id = s.idWHEN MATCHED THEN UPDATE SET last_updated = current_date()WHEN NOT MATCHED THEN INSERT * EXCEPT (last_updated, internal_count) |
INSERT genera un error porque la columna internal_count no existe en la tabla de destino. |
Las filas coincidentes se actualizan estableciendo el campo last_updated en la fecha actual. El campo review se agrega a la tabla de destino, pero se omite el campo internal_count. Las filas nuevas insertadas tienen last_updated establecido en null. |
Activar la evolución del esquema con la configuración de Spark (heredada)
Puede establecer la configuración spark.databricks.delta.schema.autoMerge.enabled en true para habilitar la evolución del esquema para todas las operaciones de escritura en la SparkSession actual.
Pitón
spark.conf.set("spark.databricks.delta.schema.autoMerge.enabled", True)
Scala
spark.conf.set("spark.databricks.delta.schema.autoMerge.enabled", true)
SQL
SET spark.databricks.delta.schema.autoMerge.enabled=true
Importante
Este enfoque no se recomienda para su uso en producción. En su lugar, habilite la evolución del esquema para cada operación de escritura:
- Para
INSERTescrituras por lotes y streaming, use.option("mergeSchema", "true") - Para
MERGEdeclaraciones, useMERGE WITH SCHEMA EVOLUTION
Establecer una configuración en toda la sesión puede provocar cambios de esquema no deseados en varias operaciones y dificulta la razón de qué operaciones evolucionan el esquema.
Cuando se usan opciones o sintaxis para habilitar la evolución del esquema en una operación de escritura, esto tiene prioridad sobre la configuración de Spark.
Trabajar con columnas NullType en actualizaciones de esquemas
Dado que Parquet no admite NullType, las columnas NullType se eliminan del DataFrame al escribir en tablas, pero todavía se almacenan en el esquema. Cuando se recibe un tipo de datos diferente para esa columna, el esquema se combina con el nuevo tipo de datos. Si se recibe un NullType para una columna existente, se conserva el esquema antiguo y la nueva columna se quita durante la escritura.
No se admite NullType en streaming. Como debe establecer esquemas al usar el streaming, esto debería ser muy poco frecuente.
NullType tampoco se acepta para tipos complejos, como ArrayType y MapType.
Reemplazar esquema de tabla
De manera predeterminada, la sobrescritura de los datos en una tabla no sobrescribe el esquema. Al sobrescribir una tabla mediante mode("overwrite") sin replaceWhere, puede que desee sobrescribir también el esquema de los datos que se están escribiendo. Reemplace el esquema y la creación de particiones de la tabla estableciendo la opción overwriteSchema en true:
df.write.option("overwriteSchema", "true")
Importante
No se puede especificar overwriteSchema como true cuando se usa la sobrescritura de partición dinámica.