Partager via


Convertir une table étrangère en table de catalogue Unity externe

Important

Cette fonctionnalité est disponible en préversion publique et est disponible uniquement pour les clients participants pour l’instant. Pour participer à l'aperçu, remplissez ce formulaire. Cette fonctionnalité prend uniquement en charge la conversion de tables étrangères fédérées à l’aide de HMS et de glue Federation.

Cette page explique comment utiliser SET EXTERNAL pour convertir une table étrangère en table externe.

Vue d’ensemble de SET EXTERNAL

Utilisez la SET EXTERNAL fonctionnalité pour convertir une table étrangère en table Unity Catalog EXTERNAL dans Azure Databricks. SET EXTERNAL offre les avantages suivants :

  • Conservation de l’historique des tables
  • Conservez les mêmes configurations de table, notamment le même nom, les mêmes paramètres, autorisations et vues.

Prerequisites

  • Format des données : le format de données de la table étrangère doit être l’un des éléments suivants :
    • Delta
    • Parquet
    • ORC
    • Avro
    • JSON
    • CSV
    • TEXTE
  • Type de table : le type de table HMS doit être une table HMS externe. La commande échoue si la table est une table HMS gérée.
  • Runtime : Databricks Runtime 17.3 ou version ultérieure
  • Autorisations : OWNER ou MANAGE autorisations sur la table et CREATE autorisation sur le EXTERNAL LOCATION

Avertissement

Les écritures simultanées dans la table source et à partir du catalogue Unity ne sont pas prises en charge. Vous êtes responsable de la désactivation des lectures et des écritures dans la table source dans le catalogue externe et de vous assurer que les charges de travail ont migré vers le nouveau catalogue avant d’effectuer la conversion.

Syntaxe

Pour convertir votre table étrangère du catalogue Unity en table externe du catalogue Unity, exécutez la commande suivante :

ALTER TABLE source_table SET EXTERNAL [DRY RUN]

Paramètres

  • source_table

    Table de données étrangère existante dans le catalogue Unity. Les tables étrangères contiennent des données et des métadonnées gérées par un catalogue externe. Avant la conversion, si vous supprimez la table source dans le catalogue externe, la table étrangère est également supprimée dans le catalogue Unity. Une fois la table convertie en externe, la suppression de la table source dans le catalogue externe n’affecte pas la table externe du catalogue Unity.

  • DRY RUN

    Quand elle est spécifiée, vérifie si la table source peut être mise à niveau sans mettre à niveau les tables cibles. La commande retourne DRY_RUN_SUCCESS si une table peut être mise à niveau.

Rollback

Pour restaurer la migration de la table, supprimez-la ; elle sera ensuite de nouveau fédérée en tant que table externe lors de la synchronisation de catalogue suivante.

DROP TABLE catalog.schema.my_external_table;

Vérifier la conversion

Vous pouvez confirmer que votre table étrangère a été convertie en table externe en consultant l’Explorateur de catalogues. Avant la conversion, la table s’affiche sous la forme Foreign, et après la conversion, elle s’affiche en tant qu’externe.

Note

L’exécution DESCRIBE EXTENDED affiche le type de table comme EXTERNAL avant et après la conversion. Cela est dû au mode de fonctionnement de Federation, car il reproduit le comportement d’exécution de cette commande dans le catalogue hive_metastore. Pour vérifier avec précision la conversion, utilisez l’Explorateur de catalogues.

Questions fréquentes (FAQ)

Puis-je créer des tables et convertir des tables dans un catalogue étranger ?

Oui, vous pouvez créer des tables externes ou gérées dans un catalogue étranger. Le comportement dépend de la configuration du schéma :

  • Pour les schémas Glue ou eHMS, ou pour les schémas avec un emplacement managé défini dans le catalogue Unity : si vous exécutez CREATE TABLE foreign_catalog.schema.table, cela crée une table managée ou externe du catalogue Unity. La table n’est pas transférée et synchronisée vers le catalogue externe.
  • Pour les schémas des connexions de metastore Hive internes : si vous essayez de créer une table dans un schéma étranger, elle crée toujours une table étrangère et crée également une table dans hive_metastore.
  • Pour le metastore Hive de l'ancien espace de travail : étant donné qu’il s’agit d’une fédération en lecture et écriture, si vous créez une table dans le catalogue externe, il crée également une table dans le metastore Hive interne.

Que se passe-t-il si mes tables étrangères sont au format SerDe ?

Pour les tables Parquet SerDe dans AWS Glue, vous devez modifier les métadonnées de la table avant de les convertir en table externe. Le script Python suivant utilise la bibliothèque AWS boto3 pour mettre à jour les propriétés nécessaires :

import boto3
import json

# Initialize boto3 Glue client with your AWS region
glue_client = boto3.client('glue', region_name='<your-aws-region>')  # Example: 'us-west-2'

# Configure your table details
DATABASE_NAME = '<your-database-name>'  # Example: 'my_database'
TABLE_NAME = '<your-table-name>'  # Example: 'my_parquet_table'
SPARK_PROVIDER = 'PARQUET'
SPARK_PARTITION_PROVIDER = 'filesystem'

# Step 1: Get the current table definition
print(f"Retrieving current table definition for {DATABASE_NAME}.{TABLE_NAME}...")
response = glue_client.get_table(DatabaseName=DATABASE_NAME, Name=TABLE_NAME)

# Extract the table's current definition
table_definition = response['Table']

# Step 2: Verify if the table is a Parquet SerDe
serde_library = table_definition['StorageDescriptor']['SerdeInfo'].get('SerializationLibrary', '')
is_parquet_serde = serde_library == "org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe"

if not is_parquet_serde:
    print(f"The table {TABLE_NAME} does not use a Parquet SerDe. Found: {serde_library}")
else:
    print(f"Table {TABLE_NAME} is using a Parquet SerDe.")

    # Step 3: Extract the S3 path dynamically from the Location field
    s3_path = table_definition['StorageDescriptor']['Location']
    print(f"S3 Path found: {s3_path}")

    # Step 4: Modify the SerDe and table properties
    # Modify SerDe parameters
    if 'SerdeInfo' in table_definition['StorageDescriptor']:
        if 'Parameters' not in table_definition['StorageDescriptor']['SerdeInfo']:
            table_definition['StorageDescriptor']['SerdeInfo']['Parameters'] = {}
        table_definition['StorageDescriptor']['SerdeInfo']['Parameters']['path'] = s3_path

    # Modify table properties
    if 'Parameters' not in table_definition:
        table_definition['Parameters'] = {}

    # Set both spark.sql.sources.provider and spark.sql.partitionProvider
    table_definition['Parameters']['spark.sql.sources.provider'] = SPARK_PROVIDER
    table_definition['Parameters']['spark.sql.partitionProvider'] = SPARK_PARTITION_PROVIDER

    # Remove metadata fields that are not accepted by update_table API
    table_definition.pop('CreateTime', None)
    table_definition.pop('UpdateTime', None)
    table_definition.pop('LastAccessTime', None)
    table_definition.pop('Retention', None)
    table_definition.pop("DatabaseName", None)
    table_definition.pop('CreatedBy', None)
    table_definition.pop('IsRegisteredWithLakeFormation', None)
    table_definition.pop('CatalogId', None)
    table_definition.pop('VersionId', None)

    # Step 5: Update the table with the modified properties
    print(f"Updating the table {TABLE_NAME} in Glue...")
    response = glue_client.update_table(
        DatabaseName=DATABASE_NAME,  # Correct use of DatabaseName
        TableInput=table_definition,
    )

    print(f"Table {TABLE_NAME} updated successfully!")

Que se passe-t-il si mes tables étrangères sont basées sur DBFS ?

Lors de la conversion d’une table sauvegardée par DBFS, nous stockons le mappage actuel du chemin DBFS vers le chemin cloud comme emplacement du chemin d’accès cloud de la table externe.

Puis-je convertir au niveau du schéma ou du catalogue ?

Vous pouvez parcourir vos tables dans vos schémas pour les convertir individuellement, ou utiliser le projet discoverx labs pour convertir des schémas ou catalogues entiers en même temps :

df = (dx.from_tables("prod.*.*")
.with_sql("ALTER TABLE {full_table_name} SET EXTERNAL;")
.apply())  # dry run with .explain()