Mettre à jour un schéma de table Delta Lake
Delta Lake vous permet de mettre à jour le schéma d’une table. Les types d’applications suivants sont pris en charge :
- Ajout de nouvelles colonnes (à des positions arbitraires)
- Réorganisation des colonnes existantes
- Attribution d’un nouveau nom aux colonnes existantes
Vous pouvez apporter ces modifications explicitement à l’aide de DDL ou implicitement à l’aide de DML.
Important
Une mise à jour d’un schéma de table Delta est une opération qui entre en conflit avec toutes les opérations d’écriture Delta simultanées.
Lorsque vous mettez à jour un schéma de table Delta, les flux qui lisent à partir de cette table se terminent. Si vous souhaitez que le flux continue, vous devez le redémarrer. Pour plus d’informations, consultez Considérations relatives à la production pour les applications Structured Streaming.
Mettre à jour explicitement le schéma pour ajouter des colonnes
ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)
Par défaut, la nullité est true
.
Pour ajouter une colonne à un champ imbriqué, utilisez :
ALTER TABLE table_name ADD COLUMNS (col_name.nested_col_name data_type [COMMENT col_comment] [FIRST|AFTER colA_name], ...)
Par exemple, si le schéma avant l’exécution de ALTER TABLE boxes ADD COLUMNS (colB.nested STRING AFTER field1)
est :
- root
| - colA
| - colB
| +-field1
| +-field2
le schéma après est :
- root
| - colA
| - colB
| +-field1
| +-nested
| +-field2
Notes
L’ajout de colonnes imbriquées est pris en charge uniquement pour les structs. Les tableaux et les mappages ne sont pas pris en charge.
Mettre à jour explicitement le schéma pour modifier le commentaire ou l’ordre des colonnes
ALTER TABLE table_name ALTER [COLUMN] col_name (COMMENT col_comment | FIRST | AFTER colA_name)
Pour modifier une colonne dans un champ imbriqué, utilisez :
ALTER TABLE table_name ALTER [COLUMN] col_name.nested_col_name (COMMENT col_comment | FIRST | AFTER colA_name)
Par exemple, si le schéma avant l’exécution de ALTER TABLE boxes ALTER COLUMN colB.field2 FIRST
est :
- root
| - colA
| - colB
| +-field1
| +-field2
le schéma après est :
- root
| - colA
| - colB
| +-field2
| +-field1
Mettre à jour explicitement le schéma pour remplacer les colonnes
ALTER TABLE table_name REPLACE COLUMNS (col_name1 col_type1 [COMMENT col_comment1], ...)
Par exemple, lors de l’exécution de la commande DDL suivante :
ALTER TABLE boxes REPLACE COLUMNS (colC STRING, colB STRUCT<field2:STRING, nested:STRING, field1:STRING>, colA STRING)
si le schéma avant est :
- root
| - colA
| - colB
| +-field1
| +-field2
le schéma après est :
- root
| - colC
| - colB
| +-field2
| +-nested
| +-field1
| - colA
Mettre à jour explicitement le schéma pour renommer des colonnes
Important
Cette fonctionnalité est disponible en préversion publique.
Remarque
Cette fonctionnalité est disponible sur Databricks Runtime 10.4 LTS et versions ultérieures.
Pour renommer des colonnes sans réécrire les données existantes des colonnes, vous devez activer le mappage de colonnes pour la table. Cf. Renommage et suppression des colonnes avec le mappage de colonnes Delta Lake.
Pour renommer une colonne :
ALTER TABLE table_name RENAME COLUMN old_col_name TO new_col_name
Pour renommer un champ imbriqué :
ALTER TABLE table_name RENAME COLUMN col_name.old_nested_field TO new_nested_field
Par exemple, lorsque vous exécutez la commande suivante :
ALTER TABLE boxes RENAME COLUMN colB.field1 TO field001
Si le schéma avant est :
- root
| - colA
| - colB
| +-field1
| +-field2
Alors le schéma après est :
- root
| - colA
| - colB
| +-field001
| +-field2
Cf. Renommage et suppression des colonnes avec le mappage de colonnes Delta Lake.
Mettre à jour explicitement le schéma pour supprimer des colonnes
Important
Cette fonctionnalité est disponible en préversion publique.
Remarque
Cette fonctionnalité est disponible dans Databricks Runtime 11.3 LTS et versions ultérieures.
Pour supprimer des colonnes en tant qu’opération de métadonnées uniquement sans réécriture de fichiers de données, vous devez activer le mappage de colonnes pour la table. Cf. Renommage et suppression des colonnes avec le mappage de colonnes Delta Lake.
Important
La suppression d’une colonne des métadonnées ne supprime pas les données sous-jacentes de la colonne dans les fichiers. Pour vider les données de colonne supprimées, vous pouvez utiliser REORG TABLE pour réécrire des fichiers. Vous pouvez ensuite utiliser VACUUM pour supprimer physiquement les fichiers qui contiennent les données de colonne supprimées.
Pour supprimer une colonne :
ALTER TABLE table_name DROP COLUMN col_name
Pour supprimer plusieurs colonnes :
ALTER TABLE table_name DROP COLUMNS (col_name_1, col_name_2)
Mettre à jour explicitement le schéma pour modifier le type ou le nom de la colonne
Vous pouvez modifier le type ou le nom d’une colonne ou supprimer une colonne en réécrivant la table. Pour ce faire, utilisez l’option overwriteSchema
.
L’exemple suivant illustre la modification d’un type de colonne :
(spark.read.table(...)
.withColumn("birthDate", col("birthDate").cast("date"))
.write
.mode("overwrite")
.option("overwriteSchema", "true")
.saveAsTable(...)
)
L’exemple suivant illustre la modification d’un nom de colonne :
(spark.read.table(...)
.withColumnRenamed("dateOfBirth", "birthDate")
.write
.mode("overwrite")
.option("overwriteSchema", "true")
.saveAsTable(...)
)
Ajouter des colonnes avec mise à jour automatique du schéma
Les colonnes qui sont présentes dans le tableau mais qui sont absentes de la table sont automatiquement ajoutées dans le cadre d’une transaction d’écriture dans les cas suivants :
write
ouwriteStream
ont.option("mergeSchema", "true")
spark.databricks.delta.schema.autoMerge.enabled
esttrue
Lorsque les deux options sont spécifiées, l’option de DataFrameWriter
est prioritaire. Les colonnes ajoutées sont ajoutées à la fin du struct dans lequel elles sont présentes. La casse est conservée lors de l’ajout d’une nouvelle colonne.
Notes
mergeSchema
ne peut pas être utilisé avecINSERT INTO
ou.write.insertInto()
.
Évolution automatique du schéma pour la fusion Delta Lake
L’évolution du schéma permet aux utilisateurs de résoudre les incompatibilités de schéma entre la table cible et la table source dans la fusion. Il gère les deux cas suivants :
- Une colonne de la table source n’est pas présente dans la table cible. La nouvelle colonne est ajoutée au schéma cible et ses valeurs sont insérées ou mises à jour à l’aide des valeurs sources.
- Une colonne dans la table cible n’est pas présente dans la table source. Le schéma cible reste inchangé ; les valeurs de la colonne cible supplémentaire sont laissées inchangées (pour
UPDATE
) ou définies surNULL
(pourINSERT
).
Important
Pour utiliser l’évolution du schéma, vous devez définir la configuration de session Sparkspark.databricks.delta.schema.autoMerge.enabled
sur true
avant d’exécuter la commande merge
.
Remarque
- Dans Databricks Runtime 12.2 LTS et versions ultérieures, les colonnes présentes dans la table source peuvent être spécifiées par leur nom dans les actions d’insertion ou de mise à jour. Dans Databricks Runtime 11.3 LTS et versions antérieures, seules les actions
INSERT *
ouUPDATE SET *
peuvent être utilisées pour l’évolution du schéma avec la fusion.
Voici quelques exemples des effets de l’opération merge
avec et sans évolution du schéma.
Colonnes | Requête (dans SQL) | Comportement sans évolution du schéma (par défaut) | Comportement avec évolution du schéma |
---|---|---|---|
Colonnes cibles : key, value Colonnes sources : key, value, new_value |
MERGE INTO target_table t USING source_table s ON t.key = s.key WHEN MATCHED THEN UPDATE SET * WHEN NOT MATCHED THEN INSERT * |
Le schéma de la table reste inchangé. Seules les colonnes key et value sont mises à jour/insérées. |
Le schéma de la table est modifié en (key, value, new_value) . Les enregistrements existants avec des correspondances sont mis à jour avec le value et le new_value dans la source. Les nouvelles lignes sont insérées avec le schéma (key, value, new_value) . |
Colonnes cibles : key, old_value Colonnes sources : key, new_value |
MERGE INTO target_table t USING source_table s ON t.key = s.key WHEN MATCHED THEN UPDATE SET * WHEN NOT MATCHED THEN INSERT * |
Les actions UPDATE et INSERT génèrent une erreur parce que la colonne cible old_value ne figure pas dans la source |
Le schéma de la table est modifié en (key, old_value, new_value) . Les enregistrements existants avec des correspondances sont mis à jour avec le new_value dans la source, laissant le old_value inchangé. Les nouveaux enregistrements sont insérés avec les key , new_value et NULL spécifiés pour le old_value . |
Colonnes cibles : key, old_value Colonnes sources : key, new_value |
MERGE INTO target_table t USING source_table s ON t.key = s.key WHEN MATCHED THEN UPDATE SET new_value = s.new_value |
UPDATE génère une erreur parce que la colonne new_value n’existe pas dans la table cible. |
Le schéma de la table est modifié en (key, old_value, new_value) . Les enregistrements existants avec des correspondances sont mis à jour avec le new_value dans la source, laissant le old_value inchangé, et les enregistrements sans correspondance ont NULL entré pour le new_value . Voir la remarque (1). |
Colonnes cibles : key, old_value Colonnes sources : key, new_value |
MERGE INTO target_table t USING source_table s ON t.key = s.key WHEN NOT MATCHED THEN INSERT (key, new_value) VALUES (s.key, s.new_value) |
INSERT génère une erreur parce que la colonne new_value n’existe pas dans la table cible. |
Le schéma de la table est modifié en (key, old_value, new_value) . Les nouveaux enregistrements sont insérés avec les key , new_value et NULL spécifiés pour le old_value . Les enregistrements existants ont NULL entré pour new_value , laissant old_value inchangé. Voir la remarque (1). |
(1) Ce comportement est disponible dans Databricks Runtime 12.2 LTS et versions ultérieures. Databricks Runtime 11.3 LTS et versions antérieures présentent une erreur dans cette condition.
Exclure des colonnes avec la fusion Delta Lake
Dans Databricks Runtime 12.2 LTS et versions ultérieures, vous pouvez utiliser des clauses EXCEPT
dans des conditions de fusion pour exclure explicitement des colonnes. Le comportement du mot clé EXCEPT
varie selon que l’évolution du schéma est activée.
Si l’évolution du schéma est désactivée, le mot clé EXCEPT
s’applique à la liste des colonnes de la table cible et permet d’exclure les colonnes des actions UPDATE
ouINSERT
. Les colonnes exclues sont définies sur null
.
Si l’évolution du schéma est activée, le mot clé EXCEPT
s’applique à la liste des colonnes de la table source et permet d’exclure les colonnes de l’évolution du schéma. Une nouvelle colonne dans la source qui n’est pas présente dans la cible n’est pas ajoutée au schéma cible si elle est répertoriée dans la clause EXCEPT
. Les colonnes exclues qui sont déjà présentes dans la cible sont définies sur null
.
Les exemples ci-dessous illustrent cette syntaxe :
Colonnes | Requête (dans SQL) | Comportement sans évolution du schéma (par défaut) | Comportement avec évolution du schéma |
---|---|---|---|
Colonnes cibles : id, title, last_updated Colonnes sources : id, title, review, last_updated |
MERGE INTO target t USING source s ON t.id = s.id WHEN MATCHED THEN UPDATE SET last_updated = current_date() WHEN NOT MATCHED THEN INSERT * EXCEPT (last_updated) |
Les lignes correspondantes sont mises à jour en définissant le champ last_updated sur la date actuelle. Les nouvelles lignes sont insérées à l’aide de valeurs pour id et title . Le champ exclu last_updated est défini sur null . Le champ review est ignoré, car il n’est pas dans la cible. |
Les lignes correspondantes sont mises à jour en définissant le champ last_updated sur la date actuelle. Le schéma est évolué pour ajouter le champ review . Les nouvelles lignes sont insérées à l’aide de tous les champs sources, à l’exception de last_updated , qui est défini sur null . |
Colonnes cibles : id, title, last_updated Colonnes sources : id, title, review, internal_count |
MERGE INTO target t USING source s ON t.id = s.id WHEN MATCHED THEN UPDATE SET last_updated = current_date() WHEN NOT MATCHED THEN INSERT * EXCEPT (last_updated, internal_count) |
INSERT génère une erreur parce que la colonne internal_count n’existe pas dans la table cible. |
Les lignes correspondantes sont mises à jour en définissant le champ last_updated sur la date actuelle. Le champ review est ajouté à la table cible, mais le champ internal_count est ignoré. Pour les nouvelles lignes insérées, le champ last_updated est défini sur null . |
Évolution automatique du schéma pour les tableaux de structs
L’opération Delta MERGE INTO
prend en charge la résolution des champs struct par nom, et l’évolution des schémas pour les tableaux de structs. Avec l’évolution du schéma activée, les schémas de table cible évoluent pour les tableaux de structs. Cela fonctionne également avec tous les structs imbriqués à l’intérieur de tableaux.
Remarque
Dans Databricks Runtime 12.2 LTS et versions ultérieures, vous pouvez spécifier les champs struct présents dans la table source par leur nom dans les commandes d’insertion ou de mise à jour. Dans Databricks Runtime 11.3 LTS et versions antérieures, seules les commandes INSERT *
ou UPDATE SET *
peuvent être utilisées pour l’évolution du schéma avec la fusion.
Voici quelques exemples des effets des opérations de fusion avec et sans évolution de schéma pour les tableaux de structs.
source_schema | Schéma cible | Comportement sans évolution du schéma (par défaut) | Comportement avec évolution du schéma |
---|---|---|---|
array<struct<b: string, a: string>> | array<struct<a: int, b: int>> | Le schéma de la table reste inchangé. Les colonnes seront résolues par nom, puis mises à jour ou insérées. | Le schéma de la table reste inchangé. Les colonnes seront résolues par nom, puis mises à jour ou insérées. |
array<struct<a: int, c: string, d: string>> | array<struct<a: string, b: string>> | update et insert génèrent des erreurs parce que c et d n’existent pas dans la table cible. |
Le schéma de la table est modifié en array<struct<a: string, b: string, c: string, d: string>>. c et d sont insérés comme NULL pour les entrées existantes dans la table cible. update et insert remplissent les entrées dans la table source avec a converti en chaîne et b en tant que NULL . |
array<struct<a: string, b: struct<c: string, d: string>>> | array<struct<a: string, b: struct<c: string>>> | update et insert génèrent des erreurs parce que d n’existe pas dans la table cible. |
Le schéma de la table cible est modifié en array<struct<a: string, b: struct<c: string, d: string>>>. d est insérés comme NULL pour les entrées existantes dans la table cible. |
Traitement des colonnes NullType
dans les mises à jour de schéma
Comme parquet ne prend pas en charge NullType
, NullType
les colonnes sont supprimées du tableau lors de l’écriture dans les tables delta, mais elles sont toujours stockées dans le schéma. Lorsqu’un type de données différent est reçu pour cette colonne, Delta Lake fusionne le schéma avec le nouveau type de données. Si Delta Lake reçoit une NullType
pour une colonne existante, l’ancien schéma est conservé et la nouvelle colonne est supprimée pendant l’écriture.
NullType
la diffusion en continu n’est pas prise en charge. Étant donné que vous devez définir des schémas lors de l’utilisation de la diffusion en continu, cela doit être très rare. NullType
n’est pas non plus accepté pour les types complexes tels que ArrayType
et MapType
.
Remplacer un schéma de table
Par défaut, le remplacement des données dans une table ne remplace pas le schéma. Lors du remplacement d’une table à l’aide mode("overwrite")
de sans replaceWhere
, vous souhaiterez peut-être quand même remplacer le schéma des données en cours d’écriture. Vous remplacez le schéma et le partitionnement de la table en affectant à l’option overwriteSchema
à la true
:
df.write.option("overwriteSchema", "true")
Important
Vous ne pouvez pas spécifier overwriteSchema
comme true
lors de l’utilisation du remplacement de partition dynamique.