Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
As tabelas dão suporte à evolução do esquema, permitindo modificações na estrutura da tabela à medida que os requisitos de dados são alterados. Há suporte aos seguintes tipos de alterações:
- Adicionando novas colunas em posições arbitrárias
- Reordenação de colunas existentes
- Renomeação de colunas existentes
- Para tipos que ampliam colunas existentes, consulte Ampliar tipos com evolução automática de esquema
Faça essas alterações explicitamente usando DDL ou implicitamente usando DML.
Importante
As atualizações no esquema conflitam com todas as operações simultâneas de gravação. A Databricks recomenda coordenar as alterações de esquema para evitar conflitos de gravação.
A atualização de um esquema de tabela encerra todos os fluxos de leitura dessa tabela. Para continuar o processamento, reinicie o fluxo usando os métodos descritos nas considerações de produção para Streaming Estruturado.
Alterações manuais de esquema
Use ALTER TABLE instruções para alterar explicitamente o esquema de uma tabela sem gravar novos dados.
Adicionar colunas
Use ALTER TABLE ... ADD COLUMNS para adicionar uma ou mais colunas a uma tabela existente, opcionalmente especificando a posição e um comentário:
ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)
Por padrão, a nulabilidade é true.
Exemplo: adicionar campos aninhados
A adição de colunas aninhadas tem suporte apenas para structs. Não há suporte a matrizes e mapas.
Para adicionar uma coluna a um campo aninhado, use:
ALTER TABLE table_name ADD COLUMNS (col_name.nested_col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)
Por exemplo, se o esquema anterior à execução de ALTER TABLE boxes ADD COLUMNS (colB.nested STRING AFTER field1) for:
- root
| - colA
| - colB
| +-field1
| +-field2
o esquema após será:
- root
| - colA
| - colB
| +-field1
| +-nested
| +-field2
Alterar comentários das colunas e a ordem
Use ALTER TABLE ... ALTER COLUMN para atualizar o comentário de uma coluna ou reordená-lo em relação a outras colunas:
ALTER TABLE table_name ALTER [COLUMN] col_name (COMMENT col_comment | FIRST | AFTER colA_name)
Exemplo: alterar campos aninhados
Para alterar uma coluna em um campo aninhado, use:
ALTER TABLE table_name ALTER [COLUMN] col_name.nested_col_name (COMMENT col_comment | FIRST | AFTER colA_name)
Por exemplo, se o esquema anterior à execução de ALTER TABLE boxes ALTER COLUMN colB.field2 FIRST for:
- root
| - colA
| - colB
| +-field1
| +-field2
o esquema após será:
- root
| - colA
| - colB
| +-field2
| +-field1
Substituir colunas
Use ALTER TABLE ... REPLACE COLUMNS para redefinir a lista de colunas completa de uma tabela, incluindo adicionar, remover, reordenar ou renomear colunas em uma única operação:
ALTER TABLE table_name REPLACE COLUMNS (col_name1 col_type1 [COMMENT col_comment1], ...)
Exemplo: Substituir campos aninhados
Por exemplo, ao executar a seguinte DDL:
ALTER TABLE boxes REPLACE COLUMNS (colC STRING, colB STRUCT<field2:STRING, nested:STRING, field1:STRING>, colA STRING)
Se o esquema antes for:
- root
| - colA
| - colB
| +-field1
| +-field2
o esquema após será:
- root
| - colC
| - colB
| +-field2
| +-nested
| +-field1
| - colA
Renomear colunas
Para renomear colunas sem reescrever nenhum dos dados existentes das colunas, você deve habilitar o mapeamento de colunas para a tabela. Confira Renomear e remover colunas usando o mapeamento de colunas do Delta Lake.
Para renomear uma coluna:
ALTER TABLE table_name RENAME COLUMN old_col_name TO new_col_name
Exemplo: renomear campos aninhados
Para renomear um campo aninhado:
ALTER TABLE table_name RENAME COLUMN col_name.old_nested_field TO new_nested_field
Por exemplo, ao executar o seguinte comando:
ALTER TABLE boxes RENAME COLUMN colB.field1 TO field001
Se o esquema antes for:
- root
| - colA
| - colB
| +-field1
| +-field2
O esquema após será:
- root
| - colA
| - colB
| +-field001
| +-field2
Confira Renomear e remover colunas usando o mapeamento de colunas do Delta Lake.
Remover colunas
Para remover colunas como uma operação somente de metadados sem reescrever nenhum arquivo de dados, você precisa habilitar o mapeamento de colunas para a tabela. Confira Renomear e remover colunas usando o mapeamento de colunas do Delta Lake.
Note
A remoção de uma coluna dos metadados não exclui os dados subjacentes da coluna nos arquivos. Para limpar os dados da coluna descartada:
- Use REORG TABLE para reescrever arquivos.
- Em seguida, use VACUUM para excluir fisicamente os arquivos que contêm os dados de coluna descartados.
Para remover uma coluna:
ALTER TABLE table_name DROP COLUMN col_name
Para excluir/eliminar várias colunas:
ALTER TABLE table_name DROP COLUMNS (col_name_1, col_name_2)
Alterar o tipo ou o nome da coluna
Você pode alterar o tipo ou o nome de uma coluna ou soltar uma coluna reescrevendo a tabela. Para fazer isso, use a opção overwriteSchema.
O exemplo a seguir mostra a alteração de um tipo de coluna:
(spark.read.table(...)
.withColumn("birthDate", col("birthDate").cast("date"))
.write
.mode("overwrite")
.option("overwriteSchema", "true")
.saveAsTable(...)
)
O exemplo a seguir mostra a alteração de um nome de coluna:
(spark.read.table(...)
.withColumnRenamed("dateOfBirth", "birthDate")
.write
.mode("overwrite")
.option("overwriteSchema", "true")
.saveAsTable(...)
)
Habilitar a evolução do esquema
Use WITH SCHEMA EVOLUTION ou defina mergeSchema como true para fazer alterações de esquema com base no esquema dos dados que você deseja INSERT ou MERGE em uma tabela existente.
Habilite a evolução do esquema usando um dos seguintes métodos:
-
Use a sintaxe
INSERT WITH SCHEMA EVOLUTIONpara instruçõesINSERT. -
Use a sintaxe
MERGE WITH SCHEMA EVOLUTIONpara instruçõesMERGE. UseWITH SCHEMA EVOLUTIONna sintaxe SQL ou.withSchemaEvolution()na API do Azure Databricks. -
Defina a opção
mergeSchemapara gravações em lote ou gravações de streaming. Definir.option("mergeSchema", "true")em operações de gravação individuais. -
Definir a configuração do Spark (legada): define
spark.databricks.delta.schema.autoMerge.enabledcomotruepara toda a SparkSession.
O Databricks recomenda habilitar a evolução do esquema para cada operação de gravação usando a WITH SCHEMA EVOLUTION sintaxe ou a opção mergeSchema em vez de definir uma configuração do Spark.
Quando você usa opções ou sintaxe para habilitar a evolução do esquema em uma operação de gravação, isso tem precedência sobre a configuração do Spark.
Habilitar a evolução de esquema para operações de escrita a fim de adicionar novas colunas
Quando a evolução do esquema está habilitada, as colunas presentes na consulta de origem, mas ausentes da tabela de destino, são adicionadas automaticamente como parte de uma transação de gravação. Consulte Habilitar a evolução do esquema.
Considere o seguinte:
- As maiúsculas e minúsculas são preservadas no acréscimo de uma nova coluna.
- Novas colunas são adicionadas ao final do esquema de tabelas.
- Se as colunas adicionais estiverem em um struct, elas serão acrescentadas ao final do struct na tabela de destino.
INSERT com a evolução do schema usando SQL
Use a cláusula WITH SCHEMA EVOLUTION em instruções INSERT para permitir a evolução do esquema:
INSERT WITH SCHEMA EVOLUTION INTO target_table
SELECT * FROM source_table
Se a consulta em source_table retornar colunas que não existem na tabela de destino, essas colunas serão adicionadas automaticamente ao target_table esquema. As linhas existentes recebem NULL valores para as novas colunas.
INSERT com a evolução do esquema usando a API dataframe
O exemplo a seguir demonstra o uso da opção mergeSchema com uma operação de gravação em lote:
Python
(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 com a evolução do esquema com streaming estruturado
O exemplo a seguir demonstra o uso da opção mergeSchema com o Carregador Automático para Streaming Estruturado. Confira O que é o Carregador Automático?.
(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")
)
Evolução automática do esquema para mesclagem
Para MERGE, a evolução do esquema permite que você resolva incompatibilidades de esquema entre a tabela de destino e de origem. Ele lida com os dois casos a seguir:
Existe uma coluna na tabela de origem, mas não na tabela de destino, e é especificada pelo nome em uma atribuição de ações de inserção ou atualização. Como alternativa, uma ação
UPDATE SET *ouINSERT *está presente.Essa coluna será adicionada ao esquema de destino e seus valores serão preenchidos da coluna correspondente na origem.
Isso só se aplica quando o nome da coluna e a estrutura na fonte de mesclagem correspondem exatamente à atribuição de destino.
A nova coluna deve estar presente no esquema de origem. Atribuir a nova coluna na cláusula de ação não define essa coluna.
Estes exemplos permitem a evolução do 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 *Esses exemplos não disparam a evolução do esquema se a coluna
newcolnão estiver presente nosourceesquema:UPDATE SET target.newcol = source.someothercol UPDATE SET target.newcol = source.x + source.y UPDATE SET target.newcol = source.output.newcolExiste uma coluna na tabela de destino, mas não na tabela de origem.
O esquema de destino não é alterado. Estas colunas:
São deixados inalterados para
UPDATE SET *.Estão definidos para
NULLdeINSERT *.Ainda poderá ser explicitamente modificado caso seja atribuído na cláusula de ação.
Por exemplo:
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.
Você deve habilitar manualmente a evolução automática do esquema. Consulte Habilitar a evolução do esquema.
Note
No Databricks Runtime 11.3 LTS e abaixo, somente INSERT * ou UPDATE SET * ações podem ser usadas para evolução do esquema com mesclagem.
No Databricks Runtime 12.2 LTS e posteriores, colunas e campos de estrutura presentes na tabela de origem podem ser especificados pelo nome em ações INSERT ou UPDATE.
No Databricks Runtime 13.3 LTS e versões posteriores, você pode usar a evolução de esquema com structs aninhados em mapas, como map<int, struct<a: int, b: int>>.
MERGEcom a evolução do esquema usando SQL, Python e Scala
No Databricks Runtime 15.4 LTS ou posteriores, você pode especificar a evolução do esquema em um comando de mesclagem usando SQL ou APIs de tabela.
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
Python
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()
Operações de exemplo de MERGE com evolução de esquema
Aqui estão alguns exemplos dos efeitos da operação MERGE com e sem a evolução do esquema.
| Columns | Consulta (no SQL) | Comportamento sem a evolução do esquema (padrão) | Comportamento com a evolução do esquema |
|---|---|---|---|
Colunas de destino: key, valueColunas de origem: 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 * |
O esquema de tabela permanece inalterado; somente as colunas key, value são atualizadas/inseridas. |
O esquema da tabela é alterado para (key, value, new_value). Os registros existentes com correspondências são atualizados com value e new_value na origem. Novas linhas são inseridas com o esquema (key, value, new_value). |
Colunas de destino: key, old_valueColunas de origem: key, new_value |
MERGE INTO target_table tUSING source_table sON t.key = s.keyWHEN MATCHED THEN UPDATE SET *WHEN NOT MATCHED THEN INSERT * |
UPDATE e INSERT as ações geram um erro porque a coluna old_value de destino não está na origem. |
O esquema da tabela é alterado para (key, old_value, new_value). Os registros existentes com correspondências são atualizados com o new_value na origem deixando old_value inalterado. Novos registros são inseridos com os key, new_value e NULL especificados para o old_value. |
Colunas de destino: key, old_valueColunas de origem: 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 gera um erro porque a coluna new_value não existe na tabela de destino. |
O esquema da tabela é alterado para (key, old_value, new_value). Os registros existentes com correspondências são atualizados com o new_value na origem deixando old_value inalterado e registros não correspondentes foram NULL inseridos para new_value. Confira a observação (1). |
Colunas de destino: key, old_valueColunas de origem: 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 gera um erro porque a coluna new_value não existe na tabela de destino. |
O esquema da tabela é alterado para (key, old_value, new_value). Novos registros são inseridos com os key, new_value e NULL especificados para o old_value. Os registros existentes têm NULL inseridos para new_value deixando old_value inalterados. Confira a observação (1). |
(1) Esse comportamento está disponível no Databricks Runtime 12.2 LTS e versões superiores; o Databricks Runtime 11.3 LTS e versões anteriores gera erro nessa condição.
Excluir colunas ao mesclar
No Databricks Runtime 12.2 LTS e posteriores, você pode usar cláusulas EXCEPT em condições de mesclagem para excluir explicitamente colunas. O comportamento da palavra-chave EXCEPT varia dependendo se a evolução do esquema está habilitada ou não.
Quando a evolução do esquema é desativada, a palavra-chave EXCEPT se aplica à lista de colunas da tabela de destino e permite excluir colunas de ações UPDATE ou INSERT. As colunas excluídas são definidas como null.
Com a evolução do esquema habilitada, a palavra-chave EXCEPT se aplica à lista de colunas na tabela de origem e permite a exclusão de colunas da evolução do esquema. Uma nova coluna na origem, não presente na tabela de destino, não será adicionada ao esquema de destino se estiver listada na EXCEPT cláusula. As colunas excluídas que já existem no destino são configuradas como null.
Exemplos do EXCLUDE com o MERGE
Os exemplos a seguir demonstram essa sintaxe:
| Columns | Consulta (no SQL) | Comportamento sem a evolução do esquema (padrão) | Comportamento com a evolução do esquema |
|---|---|---|---|
Colunas de destino: id, title, last_updatedColunas de origem: 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) |
As linhas correspondentes são atualizadas definindo o campo last_updated como a data atual. Novas linhas são inseridas usando valores para id e title. O campo last_updated excluído é definido como null. O campo review é ignorado porque não está no destino. |
As linhas correspondentes são atualizadas definindo o campo last_updated como a data atual. O esquema é desenvolvido para adicionar o campo review. Novas linhas são inseridas usando todos os campos de origem, exceto last_updated, que é definida como null. |
Colunas de destino: id, title, last_updatedColunas de origem: 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 gera um erro porque a coluna internal_count não existe na tabela de destino. |
As linhas correspondentes são atualizadas definindo o campo last_updated como a data atual. O campo review é adicionado à tabela de destino, mas o campo internal_count é ignorado. Novas linhas inseridas têm last_updated definida como null. |
Habilitar a evolução de esquemas com a configuração do Spark (legada)
Você pode definir a configuração do Spark spark.databricks.delta.schema.autoMerge.enabled para true para habilitar a evolução do esquema para todas as operações de gravação no SparkSession atual.
Python
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
Note
O Databricks não recomenda essa abordagem para produção. Definir uma configuração em toda a sessão pode levar a alterações de esquema não intencionais em várias operações e torna mais difícil raciocinar sobre quais operações evoluem o esquema.
Em vez disso, habilite a evolução do esquema para cada operação de gravação:
- Para
INSERTe gravações em lote/fluxo contínuo, use.option("mergeSchema", "true")ouINSERT WITH SCHEMA EVOLUTION - Para
MERGEinstruções, useMERGE WITH SCHEMA EVOLUTION
Quando você usa opções ou sintaxe para habilitar a evolução do esquema em uma operação de gravação, isso tem precedência sobre a configuração do Spark.
Substituir esquema de tabela
Por padrão, substituir os dados em uma tabela não substitui o esquema. Ao substituir uma tabela usando mode("overwrite") sem replaceWhere, talvez você ainda queira substituir o esquema dos dados que estão sendo gravados.
Para substituir o esquema e o particionamento da tabela, defina a opção overwriteSchema como true:
df.write.option("overwriteSchema", "true")
Note
Você não pode especificar overwriteSchema como true ao usar a substituição de partição dinâmica. Consulte Substituições de partição dinâmica com partitionOverwriteMode (herdado).