Comment fonctionne le Snowflake High Performance connector for Kafka¶
Cette rubrique décrit les différents aspects du connecteur, la façon dont il fonctionne avec les tables et les canaux, et la manière de le configurer.
Comment le connecteur fonctionne-t-il avec les tables et les canaux ?¶
Le connecteur Snowflake haute performance pour Kafka exige que vous créiez manuellement les tables de destination. Le connecteur traite chaque enregistrement Kafka comme une ligne à insérer dans une table Snowflake. Par exemple, si vous avez un sujet Kafka avec le contenu du message structuré comme :
{
"order_id": 12345,
"customer_name": "John",
"order_total": 100.00,
"isPaid": true
}
Vous pouvez créer une table dont les colonnes correspondent aux clés JSON et s’appuient sur un canal par défaut nommé {tableName}-STREAMING qui mappera automatiquement les clés de premier niveau du contenu de l’enregistrement aux colonnes de la table correspondantes (insensible à la casse).
CREATE TABLE ORDERS (
record_metadata VARIANT,
order_id NUMBER,
customer_name VARCHAR,
order_total NUMBER,
ispaid BOOLEAN
);
Si vous choisissez de créer votre propre canal, vous pouvez définir la logique de transformation des données dans l’instruction COPY INTO du canal. Vous pouvez renommer les colonnes si nécessaire et convertir les types de données selon vos besoins. Par exemple :
CREATE TABLE ORDERS (
order_id VARCHAR,
customer_name VARCHAR,
order_total VARCHAR,
ispaid VARCHAR
);
CREATE PIPE ORDERS AS
COPY INTO ORDERS
FROM (
SELECT
$1:order_id::STRING,
$1:customer_name,
$1:order_total::STRING,
$1:isPaid::STRING
FROM TABLE(DATA_SOURCE(TYPE => 'STREAMING'))
);
ou
CREATE TABLE ORDERS (
topic VARCHAR,
partition VARCHAR,
order_id VARCHAR,
customer_name VARCHAR,
order_total VARCHAR,
ispaid VARCHAR
);
CREATE PIPE ORDERS AS
COPY INTO ORDERS
FROM (
SELECT
$1:RECORD_METADATA.topic::STRING AS topic,
$1:RECORD_METADATA.partition::STRING AS partition,
$1['order_id']::STRING AS order_id,
$1['customer_name']::STRING as customer_name,
CONCAT($1['order_total']::STRING, ' USD') AS order_total,
$1['isPaid']::STRING AS ispaid
FROM TABLE(DATA_SOURCE(TYPE => 'STREAMING'))
);
Lorsque vous définissez votre propre canal, les colonnes de votre table de destination ne doivent pas nécessairement correspondre aux clés JSON. Vous pouvez renommer les colonnes à l’aide des noms de votre choix et convertir les types de données selon vos besoins.
Noms de sujet, noms de table et noms de canal¶
En fonction des paramètres de configuration, le connecteur utilisera des noms différents pour la table de destination. Le nom de la table de destination est toujours dérivé du nom du sujet.
Comment le connecteur fait correspondre les noms des sujets à la table de destination¶
Le connecteur Kafka propose deux modes pour mapper les noms de sujets Kafka aux noms de tables Snowflake :
Mappage statique : Le connecteur dérive les noms des tables de destination en utilisant uniquement le nom de la rubrique Kafka.
Mode de mappage explicite de sujet à table : Vous spécifiez des mappages personnalisés entre les sujets et les tables à l’aide du paramètre de configuration
snowflake.topic2table.map
Mappage statique¶
Si vous ne configurez pas le paramètre snowflake.topic2table.map, le connecteur dérive toujours les noms de la table du nom du sujet.
Génération de noms de table :
Le connecteur dérive le nom de la table de destination à partir du nom du sujet en appliquant les règles suivantes :
Si le nom de la rubrique est un identificateur Snowflake valide (commence par une lettre ou un trait de soulignement, et ne contient que des lettres, des chiffres, des traits de soulignement ou des signes dollar), le connecteur utilise le nom de la rubrique comme nom de la table (converti en majuscules).
Si le nom du sujet contient des caractères non valides, le connecteur :
Remplace les caractères non valides par des traits de soulignement
Ajoute un trait de soulignement suivi d’un code de hachage pour garantir l’unicité
Par exemple, le sujet
my-topic.datadevientMY_TOPIC_DATA_<hash>
Détermination du nom du canal :
Le connecteur détermine le canal à utiliser en fonction de la logique suivante :
Le connecteur vérifie s’il existe un canal portant le même nom que celui de la table de destination.
S’il existe un canal créé par l’utilisateur portant ce nom, le connecteur utilise ce canal (mode de canal défini par l’utilisateur).
Si ce n’est pas le cas, le connecteur utilise le canal par défaut nommé
{tableName}-STREAMING
Note
Snowflake recommande de choisir des noms de sujets qui respectent les règles applicables aux noms d’identificateurs Snowflake afin de garantir des noms de tables prévisibles.
Comprendre RECORD_METADATA¶
Le connecteur remplit la structure RECORD_METADATA avec des métadonnées sur l’enregistrement Kafka. Ces métadonnées sont envoyées via la source de données Snowpipe Streaming à Snowflake, où elles deviennent disponibles dans les transformations de canal à l’aide de l’accesseur $1:RECORD_METADATA. La structure RECORD_METADATA est disponible en mode de canal défini par l’utilisateur et en mode de canal par défaut. Son contenu peut être enregistré dans la colonne de type. VARIANT ou des champs individuels peuvent être extraits et enregistrés dans des colonnes distinctes.
Exemple de canal avec des transformations et des métadonnées :
CREATE PIPE ORDERS AS
COPY INTO ORDERS_TABLE
FROM (
SELECT
$1:order_id::NUMBER,
$1:customer_name,
$1:order_total,
$1:RECORD_METADATA.topic AS source_topic,
$1:RECORD_METADATA.offset::NUMBER AS kafka_offset,
$1:RECORD_METADATA.SnowflakeConnectorPushTime::BIGINT AS ingestion_time
FROM TABLE(DATA_SOURCE(TYPE => 'STREAMING'))
);
Dans cet exemple :
Le canal extrait des champs spécifiques du message Kafka (id_commande, nom_client, total_commande)
Il capture également des champs de métadonnées (sujet, décalage et horodatage d’ingestion).
Les valeurs peuvent être converties et/ou transformées selon les besoins.
Comment les champs de métadonnées sont renseignés¶
Le connecteur renseigne automatiquement les champs de métadonnées en fonction des propriétés de l’enregistrement Kafka et de la configuration du connecteur. Vous pouvez contrôler les champs de métadonnées inclus à l’aide de ces paramètres de configuration :
snowflake.metadata.topic(par défaut : true) - Inclut le nom du sujetsnowflake.metadata.offset.and.partition(par défaut : true) - Inclut le décalage et la partitionsnowflake.metadata.createtime(par défaut : true) - Inclut l’horodatage de l’enregistrement Kafkasnowflake.metadata.all(par défaut : true) - Inclut toutes les métadonnées disponibles
Lorsque snowflake.metadata.all=true (par défaut), tous les champs de métadonnées sont renseignés. La définition des indicateurs de métadonnées individuels sur false exclut ces champs spécifiques de la structure RECORD_METADATA.
Note
Le champ SnowflakeConnectorPushTime est toujours disponible et représente l’heure à laquelle le connecteur a poussé l’enregistrement dans la mémoire tampon d’ingestion. Ceci est utile pour calculer la latence d’ingestion de bout en bout.
La colonne RECORD_METADATA contient les informations suivantes par défaut :
Champ |
Type de données |
Description |
|---|---|---|
topic |
Chaîne |
Le nom du sujet Kafka d’où provient l’enregistrement. |
partition |
Chaîne |
Le numéro de la partition dans le sujet. (Notez qu’il s’agit de la partition Kafka, pas de la micro-partition Snowflake.) |
offset |
number |
Le décalage dans cette partition. |
CreateTime / . LogAppendTime |
number |
Il s’agit de l’horodatage associé au message dans le sujet Kafka. La valeur est exprimée en millisecondes depuis minuit le 1er janvier 1970, UTC. Pour plus d’informations, voir https://kafka.apache.org/0100/javadoc/org/apache/kafka/clients/producer/ProducerRecord.html |
SnowflakeConnectorPushTime |
number |
Un horodatage lorsqu’un enregistrement a été transféré dans une mémoire tampon SDK Ingest. La valeur est le nombre de millisecondes depuis minuit le 1er janvier 1970, UTC. Pour plus d’informations, voir Estimation de la latence d’ingestion. |
key |
Chaîne |
Si le message est un KeyedMessage Kafka, il s’agit de la clé de ce message. Pour que le connecteur enregistre la clé dans RECORD_METADATA, le paramètre key.converter dans Propriétés de configuration de Kafka doit être défini sur « org.apache.kafka.connect.storage.StringConverter » ; sinon, le connecteur ignore les clés. |
headers |
Objet |
Un en-tête est une paire clé-valeur définie par l’utilisateur associée à l’enregistrement. Chaque enregistrement peut avoir 0, 1 ou plusieurs en-têtes. |
La quantité de métadonnées enregistrées dans la colonne RECORD_METADATA est configurable à l’aide des propriétés de configuration Kafka facultatives.
Les noms de champs et les valeurs sont sensibles à la casse.
Comment les enregistrements Kafka sont convertis avant l’ingestion¶
Avant que chaque ligne ne soit transmise à Snowpipe Streaming, le connecteur convertit la valeur de l’enregistrement Kafka Connect en Map<Chaîne, objet> dont les clés doivent correspondre aux noms de vos colonnes cibles (ou peuvent être transformées dans un canal défini par l’utilisateur). Les chaînes primaires, les tableaux d’octets ou les nombres doivent être encapsulés (par exemple en utilisant HoistField SMT) pour que le connecteur reçoive un objet structuré. Le convertisseur applique les règles suivantes :
Les valeurs nulles sont traitées comme des tombstone. Ils sont ignorés lorsque
behavior.on.null.values=IGNOREou sinon ingéré comme objets JSON vides.Les champs numériques et booléens sont transmis tels quels. Les valeurs décimales dont la précision est supérieure à 38 sont sérialisées en tant que chaînes pour rester dans les limites de
NUMBERde Snowflake.Les charges utiles
byte[]etByteBuffersont des chaînes codées en Base64 ; par conséquent, stockez-les dans les colonnesVARIANTouVARCHAR.Les tableaux restent des tableaux et les objets imbriqués restent des cartes imbriquées. Déclarez les colonnes
VARIANTlorsque vous comptez sur le canal par défaut pour atterrir les données imbriquées telles quelles.Les cartes avec des clés autres que des chaînes sont émises sous forme de paires
[key, value]car les noms des colonnes Snowflake doivent être du texte.Les en-têtes et les clés d’enregistrement sont copiés dans
RECORD_METADATAchaque fois que les indicateurs de métadonnées appropriés sont activés.
Si vous avez besoin que le corps du message entier soit conservé sous la forme d’une seule colonne, encapsulez-le dans un nouveau champ de premier niveau à l’aide des SMTs. Voir Colonne RECORD_CONTENT héritée pour le modèle de transformation.
Mode de canal défini par l’utilisateur et mode de canal par défaut¶
Le connecteur prend en charge deux modes de gestion de l’ingestion de données :
Mode de canal défini par l’utilisateur¶
Dans ce mode, vous contrôlez totalement la transformation des données et le mappage des colonnes.
** Quand utiliser ce mode :**
Vous avez besoin de noms de colonnes personnalisés différents des noms de champs JSON.
Vous devez appliquer des transformations de données (conversion de type, masquage, filtrage).
Vous souhaitez un contrôle total sur la façon dont les données sont mappées aux colonnes.
Mode de canal par défaut¶
Dans ce mode, le connecteur utilise un canal par défaut nommé {tableName}-STREAMING et mappe les champs d’enregistrement Kafka aux colonnes de table correspondant par leur nom (insensible à la casse).
** Quand utiliser ce mode :**
Les noms de votre clé d’enregistrement Kafka correspondent aux noms de colonne souhaités.
Vous n’avez pas besoin de transformations de données personnalisées.
Vous souhaitez une configuration simplifiée.
Mappage des clés d’enregistrement Kafka avec des colonnes de table avec le mode de canal par défaut
Lorsque vous utilisez le mode de canal par défaut, le connecteur utilise un canal par défaut nommé {tableName}-STREAMING et mappent les clés de premier niveau du contenu directement aux colonnes de la table en utilisant une correspondance insensible à la casse.
Utilisation du mode canal par défaut - exemple¶
Exemple 1 :¶
Considérez la charge utile de contenu de l’enregistrement kafka suivante :
{
"city": "New York",
"age": 30,
"married": true,
"has cat": true,
"@&$#* includes special characters": true,
"skills": ["sitting", "standing", "eating"],
"family": {"son": "Jack", "daughter": "Anna"}
}
Vous créez une table dont les colonnes correspondent aux clés JSON (insensibles à la casse, y compris caractères spéciaux) :
CREATE TABLE PERSON_DATA (
record_metadata VARIANT,
city VARCHAR,
age NUMBER,
married BOOLEAN,
"has cat" BOOLEAN,
"!@&$#* includes special characters" BOOLEAN,
skills VARIANT,
family VARIANT
);
Comportement de correspondance :
"city"(kafka) →cityouCITYouCity(colonne) - insensible à la casse."has cat"(kafka) →"has cat"(colonne) - doit être entre guillemets en raison de l’espace."!@&$#* includes special characters"(kafka) →"!@&$#* includes special characters"(colonne) - caractères spéciaux préservés.Les objets imbriqués comme
skillsetfamilysont mappés aux colonnes VARIANT automatiquement.
Utilisation du mode de canal défini par l’utilisateur - exemples¶
Cet exemple montre comment configurer et utiliser des canaux définis par l’utilisateur avec des transformations de données personnalisées.
Exemple 1 :¶
Créez une table avec le schéma souhaité :
CREATE TABLE ORDERS (
order_id NUMBER,
customer_name VARCHAR,
order_total NUMBER,
order_date TIMESTAMP_NTZ,
source_topic VARCHAR
);
Créez un canal qui transforme les enregistrements Kafka entrants pour qu’ils correspondent à votre schéma de table :
CREATE PIPE ORDERS AS
COPY INTO ORDERS
FROM (
SELECT
$1:order_id::NUMBER,
$1:customer_name,
$1:order_total::NUMBER,
$1:order_date::TIMESTAMP_NTZ,
$1:RECORD_METADATA.topic
FROM TABLE(DATA_SOURCE(TYPE => 'STREAMING'))
);
Notez que le nom du canal (ORDERS) correspond au nom de table (ORDERS). La définition du canal extrait les champs de la charge utile JSON utilisant la syntaxe $1:field_name et les mappe aux colonnes de la table.
Note
Vous pouvez accéder à des champs JSON imbriqués et les champs avec des caractères spéciaux utilisant la notation par crochets, comme $1['field name'] ou $1['has cat'].
Configurez le mappage entre sujet et table :
snowflake.topic2table.map=kafka-orders-topic:ORDERS
Cette configuration mappe la rubrique Kafka kafka-orders-topic à la table préexistante et au canal nommé ORDERS.
Exemple 2 :¶
Lorsque vous devez accéder à des clés dans le contenu qui n’ont pas de noms conventionnels, utilisez la syntaxe suivante :
Champs simples :
$1:field_nameChamps avec des espaces ou des caractères spéciaux :
$1['field name']ou$1['has cat']Champs avec des caractères unicode :
$1[' @&$#* has Łułósżź']Champs imbriqués :
$1:parent.childou$1:parent['child field']
Considérez cette charge utile JSON de Kafka :
{
"city": "New York",
"age": 30,
"married": true,
"has cat": true,
" @&$#* has Łułósżź": true,
"skills": ["sitting", "standing", "eating"],
"family": {"son": "Jack", "daughter": "Anna"}
}
Vous créez une table de destination avec les noms de colonnes que vous avez choisis :
CREATE TABLE PERSON_DATA (
city VARCHAR,
age NUMBER,
married BOOLEAN,
has_cat BOOLEAN,
weird_field_name BOOLEAN,
skills VARIANT,
family VARIANT
);
Créez ensuite un canal portant le même nom que celui qui définit le mappage :
CREATE PIPE PERSON_DATA AS
COPY INTO PERSON_DATA
FROM (
SELECT
$1:city,
$1:age,
$1:married,
$1['has cat'] AS has_cat,
$1[' @&$#* has Łułósżź'] AS weird_field_name,
$1:skills,
$1:family
FROM TABLE(DATA_SOURCE(TYPE => 'STREAMING'))
);
Points clés :
Vous contrôlez les noms des colonnes (par exemple, renommer
"has cat"commehas_cat)Vous pouvez convertir les types de données selon les besoins (par exemple,
$1:age::NUMBER)Vous pouvez inclure ou exclure des champs comme vous le souhaitez.
Vous pouvez ajouter des champs de métadonnées (par exemple,
$1:RECORD_METADATA.topic)Les colonnes VARIANT traitent automatiquement les structures JSON imbriquées
Exemple 3 : avec les tables interactives¶
Les tables interactives sont un type spécial de table Snowflake optimisée pour les requêtes à faible latence et à forte concurrence. Vous trouverez plus d’informations sur les tables interactives dans la documentation sur les tables interactives.
Note
Actuellement, les tables interactives sont une fonction de prévisualisation disponible uniquement pour certains comptes.
Créez une table interactive :
CREATE INTERACTIVE TABLE REALTIME_METRICS ( metric_name VARCHAR, metric_value NUMBER, source_topic VARCHAR, timestamp TIMESTAMP_NTZ ) AS (SELECT $1:M_NAME::VARCHAR, $1:M_VALUE::NUMBER, $1:RECORD_METADATA.topic::VARCHAR, $1:RECORD_METADATA.timestamp::TIMESTAMP_NTZ from TABLE(DATA_SOURCE(TYPE => 'STREAMING')));
Configurez le mappage entre sujet et table :
snowflake.topic2table.map=metrics-topic:REALTIME_METRICS
Considérations importantes :
Les tables interactives ont des limitations et des restrictions de requêtes spécifiques. Consultez la documentation sur les tables interactives avant de les utiliser avec le connecteur.
Pour les tables interactives, toutes les transformations requises doivent être gérées dans la définition de la table.
Des entrepôts interactifs sont nécessaires pour interroger efficacement les tables interactives.
Mappage explicite de sujet à table¶
Lorsque vous configurez le paramètre snowflake.topic2table.map, le connecteur fonctionne en mode de mappage explicite. Ce mode vous permet de :
Mapper plusieurs sujets Kafka à une seule table Snowflake.
Utiliser des noms de tables personnalisés différents des noms de sujets.
Appliquer des modèles regex pour faire correspondre plusieurs sujets.
Format de configuration :
Le paramètre snowflake.topic2table.map accepte une liste de mappages sujets à tables séparés par des virgules au format :
topic1:table1,topic2:table2,topic3:table3
Exemples de configurations :
Mappage direct des sujets
snowflake.topic2table.map=orders:ORDER_TABLE,customers:CUSTOMER_TABLE
Correspondance de modèles Regex
snowflake.topic2table.map=.*_cat:CAT_TABLE,.*_dog:DOG_TABLE
Cette configuration mappe tous les sujets se terminant par _cat (comme orange_cat, calico_cat) à la table CAT_TABLE et tous les chapitres se terminant par _dog à la table DOG_TABLE.
Plusieurs sujets à une table
snowflake.topic2table.map=topic1:shared_table,topic2:shared_table,topic3:other_table
Cette configuration mappe à la fois topic1 et topic2 dans shared_table, tandis que topic3 est mappé à other_table.
Important
Les modèles Regex dans le mappage ne peuvent pas se chevaucher. Chaque sujet doit correspondre au maximum à un modèle.
Les noms des tables dans le mappage doivent être des identificateurs Snowflake valides comportant au moins 2 caractères, commençant par une lettre ou un trait de soulignement.
Vous pouvez mapper plusieurs sujets à une seule table.
Colonne RECORD_CONTENT héritée¶
Dans les anciennes versions du connecteur, lorsque la fonction de schématisation était désactivée, le connecteur créait une table de destination avec deux colonnes : RECORD_CONTENT et RECORD_METADATA. La colonne RECORD_CONTENT contenait la totalité du contenu du message Kafka dans la colonne de type VARIANT. La colonne RECORD_METADATA est toujours prise en charge, mais la colonne RECORD_CONTENT n’est plus créée par le connecteur. La même fonctionnalité peut être obtenue en utilisant les transformations SMT (voir des exemples plus loin dans cette section). La clé RECORD_CONTENT n’est plus disponible dans les transformations PIPE. Par exemple, cette définition PIPE ne fonctionnera pas par défaut :
Note
Cette définition de canal ne fonctionnera pas sans transformations SMT supplémentaires.
CREATE PIPE ORDERS AS
COPY INTO ORDERS
FROM (
SELECT
$1:RECORD_CONTENT
FROM TABLE(DATA_SOURCE(TYPE => 'STREAMING'))
);
Si vous voulez que l’intégralité du contenu du message Kafka soit enregistrée dans une seule colonne, ou si vous avez besoin de traiter l’intégralité du contenu du message Kafka dans une transformation PIPE, vous pouvez utiliser la transformation SMT suivante qui place l’intégralité du contenu du message Kafka dans le champ personnalisé souhaité :
transforms=wrapKafkaMessageContent
transforms.wrapKafkaMessageContent.type=org.apache.kafka.connect.transforms.HoistField$Value
transforms.wrapKafkaMessageContent.field=your_top_level_field_name
Cette transformation placera l’intégralité du contenu du message Kafka dans un champ personnalisé nommé your_top_level_field_name. Vous pouvez ensuite accéder à l’intégralité du contenu du message Kafka en utilisant l’accesseur $1:your_top_level_field_name dans votre transformation PIPE.
CREATE PIPE ORDERS AS
COPY INTO ORDERS
FROM (
SELECT
$1:your_top_level_field_name
FROM TABLE(DATA_SOURCE(TYPE => 'STREAMING'))
);
Sinon, si vous souhaitez enregistrer à la fois l’intégralité des métadonnées et du contenu dans une seule table à l’aide du canal par défaut, ne créez pas de canal personnalisé ; au lieu de cela, créez uniquement une table avec deux colonnes : RECORD_CONTENT et your_top_level_field_name.
CREATE TABLE ORDERS (
record_metadata VARIANT,
your_top_level_field_name VARIANT
);
Pour en savoir plus sur la transformation HoistField$Value, voir la documentation Kafka.
Avertissement
L’enregistrement de l’intégralité du contenu et des métadonnées des messages Kafka dans une table peut avoir un impact négatif sur votre coût d’ingestion, la vitesse du pipeline et la latence. Si vous avez besoin des meilleures performances possibles, pensez à enregistrer uniquement les données dont vous avez besoin si elles sont accessibles à partir du niveau supérieur du contenu de l’enregistrement Kafka, ou utilisez les transformations SMT pour extraire les données des champs profondément imbriqués et les placer dans des champs de premier niveau.
Gestion des erreurs de canal de streaming et des files d’attente de lettres mortes¶
Dans la version 4.0.0-rc4, le connecteur inspecte le statut du canal Snowpipe Streaming avant de valider les décalages. Si Snowflake signale des lignes rejetées (rowsErrorCount > 0), the connector now raises a fatal error (ERROR_5030) when erreurs.tolerance=none so that data issues cannot go unnoticed. To allow ingestion to continue while you triage bad rows, set error.tolerance=tout
errors.tolerance=all
Évolution du schéma¶
Important
L’évolution du schéma n’est pas prise en charge** dans le connecteur Snowflake hautes performances pour Kafka. Vous devez gérer manuellement les modifications de schéma dans vos tables de destination.
Le connecteur ne détecte pas automatiquement les modifications de schéma ni ne fait évoluer les schémas de table sur la base des enregistrements Kafka entrants. Lorsque vous devez ajouter des colonnes, modifier des types de données ou apporter d’autres modifications au schéma, vous devez :
Mettre le connecteur en pause pour arrêter l’ingestion de données
Modifier manuellement le schéma de table à l’aide de ALTER TABLE ou recréer la table
Mettre à jour la définition de vos canaux si vous utilisez des canaux définis par l’utilisateur et si la logique de transformation doit changer
Redémarrez le connecteur pour reprendre l’ingestion de données
Note
La prise en charge de l’évolution du schéma sera ajoutée dans les prochaines versions.
Tolérance aux pannes¶
Limitations de la tolérance aux pannes avec le connecteur¶
Les sujets Kafka peuvent être configurés avec une limite d’espace de stockage ou de durée de conservation.
Si le système est hors ligne pendant une durée supérieure à la durée de conservation, les enregistrements expirés ne seront pas chargés. De même, si la limite d’espace de stockage de Kafka est dépassée, certains messages ne seront pas remis.
Si les messages du sujet Kafka sont supprimés, ces modifications risquent de ne pas être reflétées dans la table Snowflake.