MaxCompute vous permet d'utiliser les opérations DELETE et UPDATE pour supprimer ou mettre à jour des données au niveau de la ligne dans les tables transactionnelles (Transactional tables) et les Delta Tables.
Prérequis
Avant d'exécuter les opérations DELETE ou UPDATE, vous devez disposer des autorisations Select et Update sur la table transactionnelle ou la Delta Table cible. Pour plus d'informations sur l'autorisation, consultez Autorisations MaxCompute.
Présentation des fonctionnalités
À l'instar de leur utilisation dans les bases de données traditionnelles, les fonctionnalités DELETE et UPDATE de MaxCompute permettent de supprimer ou de mettre à jour des lignes spécifiques d'une table.
Lorsque vous utilisez la fonctionnalité DELETE ou UPDATE, le système génère automatiquement un fichier Delta pour chaque opération de suppression ou de mise à jour. Ce fichier n'est pas visible par les utilisateurs et enregistre les informations relatives aux données supprimées ou mises à jour. Le mécanisme de fonctionnement est le suivant :
-
DELETE: le fichier Delta utilise les champstxnid(BIGINT)etrowid(BIGINT)pour identifier l'enregistrement du fichier de base d'une table transactionnelle qui a été supprimé, ainsi que l'opération de suppression correspondante. Un fichier de base constitue le format de stockage sous-jacent d'une table.Par exemple, supposons que le fichier de base de la table t1 soit f1 et que son contenu soit
a, b, c, a, b. Lorsque vous exécutez la commandeDELETE FROM t1 WHERE c1='a';, le système génère un fichierf1.deltadistinct. Si l'identifianttxnidestt0, le contenu def1.deltaest((0, t0), (3, t0)). Cela indique que la ligne 0 et la ligne 3 ont été supprimées lors de la transaction t0. Si vous exécutez une autre opérationDELETE, le système génère un autre fichier Delta, tel quef2.delta. Ce fichier fait également référence au fichier de base original f1. Lors de l'interrogation des données, le système combine le fichier de base f1 avec tous les fichiers Delta actuels pour récupérer uniquement les enregistrements qui n'ont pas été supprimés. UPDATE: une opérationUPDATEest implémentée sous la forme d'une opérationDELETEsuivie d'une opérationINSERT INTO.
Les fonctionnalités DELETE et UPDATE présentent les avantages suivants :
-
Réduction du volume de données écrites
Auparavant, MaxCompute utilisait les opérations
INSERT INTOouINSERT OVERWRITEpour supprimer ou mettre à jour les données d'une table. Pour plus d'informations, consultez Insérer ou écraser des données (INSERT INTO | INSERT OVERWRITE). Lorsque vous deviez mettre à jour une petite quantité de données dans une table ou une partition, l'utilisation d'une opérationINSERTnécessitait de lire d'abord toutes les données de la table, de mettre à jour les données via une opérationSELECT, puis de réécrire l'intégralité des données dans la table avec une opérationINSERT. Cette méthode était inefficace. Avec les fonctionnalitésDELETEouUPDATE, le système n'a pas besoin de réécrire l'ensemble des données, ce qui réduit considérablement le volume de données écrites.RemarquePour le mode de facturation au paiement à l'utilisation, les opérations d'écriture des jobs
DELETE,UPDATEetINSERT OVERWRITEne sont pas facturées. Toutefois, les jobsDELETEetUPDATEdoivent lire les données des partitions pour marquer les enregistrements à supprimer ou pour écrire les enregistrements mis à jour. Ces opérations de lecture restent facturées selon le modèle de facturation au paiement à l'utilisation pour les jobs SQL. Par conséquent, les jobsDELETEetUPDATEne réduisent pas nécessairement les coûts par rapport aux jobsINSERT OVERWRITE, même si moins de données sont écrites.Pour le mode de facturation par abonnement, les opérations
DELETEetUPDATEconsomment moins de ressources d'écriture. Par rapport àINSERT OVERWRITE, vous pouvez exécuter davantage de jobs avec les mêmes ressources.
-
Accès direct au dernier état de la table
Auparavant, MaxCompute utilisait des tables zipper pour les mises à jour de données par lots. Cette méthode nécessitait l'ajout de colonnes auxiliaires telles que
start_dateetend_dateà la table afin de suivre le cycle de vie d'un enregistrement. Pour interroger le dernier état de la table, le système devait filtrer une grande quantité de données en fonction des horodatages pour trouver l'état actuel, ce qui s'avérait complexe. Avec les fonctionnalitésDELETEetUPDATE, vous pouvez lire directement le dernier état de la table. Le système combine les fichiers de base et les fichiers Delta pour fournir la vue actuelle des données.
L'exécution répétée des opérations DELETE et UPDATE augmente le stockage sous-jacent d'une table transactionnelle. Cela entraîne une hausse des coûts de stockage et une dégradation des performances des requêtes ultérieures. Vous devez fusionner (compacter) régulièrement les données sous-jacentes. Pour plus d'informations sur les opérations de fusion, consultez UPDATE | DELETE.
Si plusieurs jobs s'exécutent simultanément sur la même table cible, des conflits de jobs peuvent survenir. Pour plus d'informations, consultez Sémantique ACID.
Cas d'utilisation
Les fonctionnalités DELETE et UPDATE sont adaptées aux suppressions ou mises à jour aléatoires et peu fréquentes d'une petite quantité de données dans une table ou une partition. Par exemple, vous pouvez effectuer quotidiennement (T+1) des suppressions ou mises à jour par lots sur moins de 5 % des lignes d'une table ou d'une partition.
Les fonctionnalités DELETE et UPDATE ne conviennent pas aux mises à jour fréquentes, aux suppressions répétées ou aux écritures en temps réel dans une table cible.
Limites
-
Les fonctionnalités
DELETEetUPDATEpeuvent être utilisées uniquement sur les tables transactionnelles et les Delta Tables, sous réserve des limites suivantes :RemarquePour plus d'informations sur les tables transactionnelles et les Delta Tables, consultez Paramètres pour Transaction Table et Delta Table.
La syntaxe
UPDATEpour les Delta Tables ne prend pas en charge la modification des colonnes de clé primaire (PK).
Précautions
Prenez en compte les éléments suivants lorsque vous utilisez les opérations DELETE ou UPDATE pour supprimer ou mettre à jour des données dans une table ou une partition :
Utilisez les opérations
DELETEetUPDATEpour supprimer ou mettre à jour une petite quantité de données dans une table, lorsque l'opération elle-même et les lectures ultérieures sont peu fréquentes. Après avoir effectué plusieurs opérations de suppression ou de mise à jour, fusionnez les fichiers de base et les fichiers Delta de la table afin de réduire son empreinte de stockage. Pour plus d'informations, consultez UPDATE | DELETE.-
Si vous supprimez ou mettez à jour un grand nombre de lignes (plus de 5 %) de manière peu fréquente, mais que les opérations de lecture ultérieures sur la table sont fréquentes, utilisez
INSERT OVERWRITEouINSERT INTO. Pour plus d'informations, consultez Insérer ou écraser des données (INSERT INTO | INSERT OVERWRITE).Par exemple, dans un scénario métier impliquant la suppression ou la mise à jour de 10 % des données 10 fois par jour, évaluez si les coûts et la dégradation des performances de lecture ultérieure liés aux opérations
DELETEetUPDATEsont inférieurs à ceux engendrés par l'utilisation deINSERT OVERWRITEouINSERT INTOpour chaque opération. Comparez l'efficacité des deux méthodes dans votre scénario spécifique pour choisir l'option la plus adaptée. La suppression de données génère des fichiers Delta, ce qui signifie que l'opération ne réduit pas immédiatement le stockage. Si vous souhaitez réduire le stockage à l'aide de l'opération
DELETE, vous devez fusionner les fichiers de base et les fichiers Delta de la table. Pour plus d'informations, consultez UPDATE | DELETE.-
MaxCompute exécute les jobs
DELETEetUPDATEen tant que processus par lots. Chaque instruction consomme des ressources et engendre des frais. Vous devez supprimer ou mettre à jour les données par lots. Par exemple, si vous utilisez un script Python pour générer et soumettre de nombreux jobs de mise à jour au niveau de la ligne, où chaque instruction ne porte que sur une ou quelques lignes, chaque instruction entraîne des coûts basés sur la quantité de données d'entrée analysées par le SQL. Le coût cumulé de nombreuses instructions de ce type augmente considérablement les dépenses et réduit l'efficacité du système. Voici des exemples de commandes.-
Méthode recommandée :
UPDATE table1 SET col1= (SELECT value1 FROM table2 WHERE table1.id = table2.id AND table1.region = table2.region); -
Méthode non recommandée :
UPDATE table1 SET col1=1 WHERE id='2021063001' AND region='beijing'; UPDATE table1 SET col1=2 WHERE id='2021063002' AND region='beijing';
-
Supprimer des données
L'opération DELETE supprime une ou plusieurs lignes répondant à des conditions spécifiées d'une table transactionnelle ou d'une Delta Table.
-
Syntaxe
DELETE FROM <table_name> [[AS] alias] [WHERE <condition>]; -
Paramètres
Paramètre
Obligatoire
Description
table_name
Oui
Nom de la table transactionnelle ou de la Delta Table sur laquelle vous souhaitez exécuter l'opération
DELETE.alias
Non
Alias de la table.
where_condition
Non
Clause WHERE permettant de filtrer les données répondant à la condition. Pour plus d'informations sur la clause WHERE, consultez Syntaxe SELECT. Si vous n'incluez pas de clause WHERE, toutes les données de la table sont supprimées.
-
Exemples
-
Exemple 1 : créez une table non partitionnée nommée acid_delete, importez des données, puis exécutez l'opération
DELETEpour supprimer les lignes répondant à une condition spécifiée. Voici les commandes d'exemple :-- Create a Transactional table named acid_delete. CREATE TABLE IF NOT EXISTS acid_delete (id BIGINT) TBLPROPERTIES ("transactional"="true"); -- Insert data. INSERT OVERWRITE TABLE acid_delete VALUES (1), (2), (3), (2); -- View the inserted data. SELECT * FROM acid_delete; +------------+ | id | +------------+ | 1 | | 2 | | 3 | | 2 | +------------+ -- Delete rows where id is 2. If you run this command on the MaxCompute client (odpscmd), you must enter yes or no to confirm. DELETE FROM acid_delete WHERE id = 2; -- The following command is equivalent to the one above. DELETE FROM acid_delete ad WHERE ad.id = 2; -- View the result. The table now contains only data for 1 and 3. SELECT * FROM acid_delete; +------------+ | id | +------------+ | 1 | | 3 | +------------+ -
Exemple 2 : créez une table partitionnée nommée acid_delete_pt, importez des données, puis exécutez l'opération
DELETEpour supprimer les lignes répondant à une condition spécifiée. Voici les commandes d'exemple :-- Create a Transactional table named acid_delete_pt. CREATE TABLE IF NOT EXISTS acid_delete_pt (id BIGINT) PARTITIONED BY (ds STRING) TBLPROPERTIES ("transactional"="true"); -- Add partitions. ALTER TABLE acid_delete_pt ADD IF NOT EXISTS PARTITION (ds = '2019'); ALTER TABLE acid_delete_pt ADD IF NOT EXISTS PARTITION (ds = '2018'); -- Insert data. INSERT OVERWRITE TABLE acid_delete_pt PARTITION (ds = '2019') VALUES (1), (2), (3); INSERT OVERWRITE TABLE acid_delete_pt PARTITION (ds = '2018') VALUES (1), (2), (3); -- View the inserted data. SELECT * FROM acid_delete_pt; +------------+------------+ | id | ds | +------------+------------+ | 1 | 2018 | | 2 | 2018 | | 3 | 2018 | | 1 | 2019 | | 2 | 2019 | | 3 | 2019 | +------------+------------+ -- Delete data where the partition is 2019 and id is 2. If you run this command on the MaxCompute client (odpscmd), you must enter yes or no to confirm. DELETE FROM acid_delete_pt WHERE ds = '2019' AND id = 2; -- View the result. The data where the partition is 2019 and id is 2 has been deleted. SELECT * FROM acid_delete_pt; +------------+------------+ | id | ds | +------------+------------+ | 1 | 2018 | | 2 | 2018 | | 3 | 2018 | | 1 | 2019 | | 3 | 2019 | +------------+------------+ -
Exemple 3 : créez une table cible nommée acid_delete_t et une table associée nommée acid_delete_s. Ensuite, supprimez les lignes répondant à une condition spécifiée via une opération de jointure. Voici les commandes d'exemple :
-- Create a target Transactional table named acid_delete_t and an associated table named acid_delete_s. CREATE TABLE IF NOT EXISTS acid_delete_t (id INT, value1 INT, value2 INT) TBLPROPERTIES ("transactional"="true"); CREATE TABLE IF NOT EXISTS acid_delete_s (id INT, value1 INT, value2 INT); -- Insert data. INSERT OVERWRITE TABLE acid_delete_t VALUES (2, 20, 21), (3, 30, 31), (4, 40, 41); INSERT OVERWRITE TABLE acid_delete_s VALUES (1, 100, 101), (2, 200, 201), (3, 300, 301); -- Delete rows from the acid_delete_t table where the id does not match an id in the acid_delete_s table. If you run this command on the MaxCompute client (odpscmd), you must enter yes or no to confirm. DELETE FROM acid_delete_t WHERE NOT EXISTS (SELECT * FROM acid_delete_s WHERE acid_delete_t.id = acid_delete_s.id); -- The following command is equivalent to the one above. DELETE FROM acid_delete_t a WHERE NOT EXISTS (SELECT * FROM acid_delete_s b WHERE a.id = b.id); -- View the result. The table now contains only data for id 2 and 3. SELECT * FROM acid_delete_t; +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 20 | 21 | | 3 | 30 | 31 | +------------+------------+------------+ -
Exemple 4 : créez une Delta Table nommée mf_dt, importez des données, puis exécutez l'opération DELETE pour supprimer les lignes répondant à une condition spécifiée. Voici les commandes d'exemple :
-- Create a target Delta Table named mf_dt. CREATE TABLE IF NOT EXISTS mf_dt (pk BIGINT NOT NULL PRIMARY KEY, val BIGINT NOT NULL) PARTITIONED BY(dd STRING, hh STRING) tblproperties ("transactional"="true"); -- Insert data. INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='02') VALUES (1, 1), (2, 2), (3, 3); -- View the inserted data. SELECT * FROM mf_dt WHERE dd='01' AND hh='02'; -- The following result is returned: +------------+------------+----+----+ | pk | val | dd | hh | +------------+------------+----+----+ | 1 | 1 | 01 | 02 | | 3 | 3 | 01 | 02 | | 2 | 2 | 01 | 02 | +------------+------------+----+----+ -- Delete data where the partition is 01 and 02, and val is 2. DELETE FROM mf_dt WHERE val = 2 AND dd='01' AND hh='02'; -- View the result. The table now contains only data where val is 1 and 3. SELECT * FROM mf_dt WHERE dd='01' AND hh='02'; -- The following result is returned: +------------+------------+----+----+ | pk | val | dd | hh | +------------+------------+----+----+ | 1 | 1 | 01 | 02 | | 3 | 3 | 01 | 02 | +------------+------------+----+----+
-
Effacer les données de colonne
Vous pouvez utiliser la commande CLEAR COLUMN pour effacer les données des colonnes d'une table standard. Cette opération supprime du disque les données qui ne sont plus utilisées et définit les valeurs de colonne sur NULL, ce qui permet de réduire les coûts de stockage.
-
Syntaxe
ALTER TABLE <table_name> [PARTITION ( <pt_spec>[, <pt_spec>....] )] CLEAR COLUMN column1[, column2, column3, ...] [WITHOUT TOUCH]; -
Paramètres
Paramètre
Description
table_name
Nom de la table dont vous souhaitez effacer les données de colonne.
column1 , column2 ...Noms des colonnes dont vous souhaitez effacer les données.
PARTITION
Spécifie la partition. Si cette option n'est pas indiquée, l'opération s'applique à toutes les partitions.
pt_spec
Description de la partition, au format
(partition_col1 = PARTITION_col_value1, PARTITION_col2 = PARTITION_col_value2, ...).WITHOUT TOUCH
Si cette option est spécifiée,
LastDataModifiedTimen'est pas mis à jour. Si cette option n'est pas spécifiée,LastDataModifiedTimeest mis à jour.RemarqueActuellement,
WITHOUT TOUCHest spécifié par défaut. Dans une version future, le comportement permettant d'effacer les données de colonne sans spécifierWITHOUT TOUCHsera pris en charge. Cela signifie que siWITHOUT TOUCHn'est pas spécifié,LastDataModifiedTimesera mis à jour. -
Limites
-
Vous ne pouvez pas effectuer d'opération d'effacement de colonne sur des colonnes comportant une contrainte NOT NULL. Vous pouvez supprimer manuellement la contrainte NOT NULL :
ALTER TABLE <table_name> change COLUMN <old_col_name> NULL; L'effacement des données de colonne n'est pas pris en charge pour les tables ACID.
L'effacement des données de colonne n'est pas pris en charge pour les tables clusterisées.
L'effacement des données de colonne au sein de types imbriqués n'est pas pris en charge.
L'effacement de toutes les colonnes n'est pas pris en charge. La commande
DROP TABLEproduit le même effet avec de meilleures performances.
-
-
Précautions
L'opération
CLEAR COLUMNne modifie pas la propriété Archive de la table.-
L'opération
CLEAR COLUMNsur une colonne de type imbriqué peut échouer.Cet échec se produit si vous effectuez une opération
CLEAR COLUMNsur une table contenant des types imbriqués en colonnes alors que le stockage en colonnes pour les types imbriqués est désactivé. La commande
CLEAR COLUMNdépend du service de stockage en ligne. La tâche peut être lente si elle doit être mise en file d'attente pendant les périodes de fort volume de jobs.L'opération
CLEAR COLUMNnécessite des ressources de calcul pour lire et écrire des données. Pour les utilisateurs par abonnement, cela consomme des ressources de calcul. Pour les utilisateurs au paiement à l'utilisation, cela engendre les mêmes frais qu'un job SQL. (Cette fonctionnalité est actuellement en aperçu sur invitation et est temporairement gratuite.)
-
Exemples
-
-- Create a table. CREATE TABLE IF NOT EXISTS mf_cc(key STRING, value STRING, a1 BIGINT , a2 BIGINT , a3 BIGINT , a4 BIGINT) PARTITIONED BY(ds STRING, hr STRING); -- Add a partition. ALTER TABLE mf_cc ADD IF NOT EXISTS PARTITION (ds='20230509', hr='1641'); -- Insert data. INSERT INTO mf_cc PARTITION (ds='20230509', hr='1641') VALUES("key","value",1,22,3,4); -- Query data. SELECT * FROM mf_cc WHERE ds='20230509' AND hr='1641'; -- The following result is returned: +-----+-------+------------+------------+--------+------+---------+-----+ | key | value | a1 | a2 | a3 | a4 | ds | hr | +-----+-------+------------+------------+--------+------+---------+-----+ | key | value | 1 | 22 | 3 | 4 | 20230509| 1641| +-----+-------+------------+------------+--------+------+---------+-----+ -- Clear column data. ALTER TABLE mf_cc PARTITION(ds='20230509', hr='1641') CLEAR COLUMN key,a1 WITHOUT TOUCH; -- Query data. SELECT * FROM mf_cc WHERE ds='20230509' AND hr='1641'; -- The following result is returned. The data in the key and a1 columns has become null. +-----+-------+------------+------------+--------+------+---------+-----+ | key | value | a1 | a2 | a3 | a4 | ds | hr | +-----+-------+------------+------------+--------+------+---------+-----+ | null| value | null | 22 | 3 | 4 | 20230509| 1641| +-----+-------+------------+------------+--------+------+---------+-----+ -
La figure suivante illustre l'évolution de la taille totale de stockage de la table
lineitem(au format AliORC) à mesure que chaque colonne est effacée à l'aide de la commandeCLEAR COLUMN. La tablelineitemcomporte 16 colonnes de divers types, notamment BIGINT, DECIMAL, CHAR, DATE et VARCHAR.
Comme vous pouvez le constater, après que les 16 colonnes de la table ont été séquentiellement définies sur NULL par la commande
CLEAR COLUMN, l'espace de stockage total est réduit de 99,97 % (passant de 186 783 526 octets initiaux à 236 715 octets).RemarqueLa quantité d'espace économisée par l'opération
CLEAR COLUMNdépend du type de données et des valeurs réellement stockées dans la colonne. Par exemple, l'effacement de la colonnel_extendedprice, qui est de type DECIMAL, a permis d'économiser 24,2 % d'espace (passant de 146 538 799 octets à 111 138 117 octets), ce qui est nettement supérieur à la moyenne.Lorsque toutes les colonnes sont définies sur NULL, la taille de la table est de 236 715 octets, et non de 0. En effet, la structure de fichier de la table existe toujours. Les champs NULL occupent une petite quantité d'espace de stockage, et le système doit également conserver les informations du pied de page du fichier.
-
Mettre à jour des données
L'opération UPDATE met à jour les valeurs d'une ou plusieurs colonnes pour les lignes d'une table transactionnelle ou d'une Delta Table.
-
Syntaxe
-- Method 1 UPDATE <table_name> [[AS] alias] SET <col1_name> = <value1> [, <col2_name> = <value2> ...] [WHERE <where_condition>]; -- Method 2 UPDATE <table_name> [[AS] alias] SET (<col1_name> [, <col2_name> ...]) = (<value1> [, <value2> ...]) [WHERE <where_condition>]; -- Method 3 UPDATE <table_name> [[AS] alias] SET <col1_name> = <value1> [, <col2_name> = <value2>, ...] [FROM <additional_tables>] [WHERE <where_condition>]; -
Paramètres
table_name : obligatoire. Nom de la table transactionnelle ou de la Delta Table pour l'opération
UPDATE.alias : facultatif. Alias de la table.
col1_name, col2_name : obligatoires. Noms des colonnes à modifier. Vous devez mettre à jour au moins une colonne.
value1, value2 : obligatoires. Nouvelles valeurs des colonnes. Vous devez mettre à jour au moins une valeur de colonne.
where_condition : facultatif. Clause WHERE permettant de filtrer les données. Pour plus d'informations sur la clause WHERE, consultez Syntaxe SELECT. Si vous n'incluez pas de clause WHERE, toutes les données de la table sont mises à jour.
-
additional_tables : facultatif. Clause FROM.
L'instruction
UPDATEprend en charge la clause FROM, ce qui peut simplifier l'instructionUPDATE. Le tableau suivant compare une instruction UPDATE utilisant une clause FROM à une instruction n'en utilisant pas.Scénario
Exemple de code
Sans clause FROM
UPDATE target SET v = (SELECT MIN(v) FROM src GROUP BY k WHERE target.k = src.key) WHERE target.k IN (SELECT k FROM src);Avec clause FROM
UPDATE target SET v = b.v FROM (SELECT k, MIN(v) AS v FROM src GROUP BY k) b WHERE target.k = b.k;Comme le montrent les exemples de code :
Lorsque vous mettez à jour une ligne de la table cible en utilisant plusieurs lignes de la table source, vous devez utiliser une opération d'agrégation pour garantir l'unicité des données source, car le système ne sait pas quelle ligne source utiliser. La syntaxe n'utilisant pas de clause
FROMest moins concise. La syntaxe avec une clauseFROMest plus simple et plus facile à comprendre.Lors d'une mise à jour par jointure, si vous souhaitez mettre à jour uniquement l'intersection des données, la syntaxe n'utilisant pas de clause
FROMnécessite une conditionWHEREsupplémentaire et est moins concise que la syntaxe utilisant une clauseFROM.
-
Exemples
-
Exemple 1 : créez une table non partitionnée nommée acid_update, importez des données, puis exécutez l'opération
UPDATEpour mettre à jour les colonnes des lignes répondant à une condition spécifiée. Voici les commandes d'exemple :-- Create a Transactional table named acid_update. CREATE TABLE IF NOT EXISTS acid_update(id BIGINT) tblproperties ("transactional"="true"); -- Insert data. INSERT OVERWRITE TABLE acid_update VALUES(1),(2),(3),(2); -- View the inserted data. SELECT * FROM acid_update; -- The following result is returned: +------------+ | id | +------------+ | 1 | | 2 | | 3 | | 2 | +------------+ -- Update the id value to 4 for all rows where id is 2. UPDATE acid_update SET id = 4 WHERE id = 2; -- View the update result. 2 has been updated to 4. SELECT * FROM acid_update; -- The following result is returned: +------------+ | id | +------------+ | 1 | | 3 | | 4 | | 4 | +------------+ -
Exemple 2 : créez une table partitionnée nommée acid_update, importez des données, puis exécutez l'opération
UPDATEpour mettre à jour les colonnes des lignes répondant à une condition spécifiée. Voici les commandes d'exemple :-- Create a Transactional table named acid_update_pt. CREATE TABLE IF NOT EXISTS acid_update_pt(id BIGINT) PARTITIONED BY(ds STRING) tblproperties ("transactional"="true"); -- Add a partition. ALTER TABLE acid_update_pt ADD IF NOT EXISTS PARTITION (ds= '2019'); -- Insert data. INSERT OVERWRITE TABLE acid_update_pt PARTITION (ds='2019') VALUES(1),(2),(3); -- View the inserted data. SELECT * FROM acid_update_pt WHERE ds = '2019'; -- The following result is returned: +------------+------------+ | id | ds | +------------+------------+ | 1 | 2019 | | 2 | 2019 | | 3 | 2019 | +------------+------------+ -- Update a column in a specified row. Set the id value to 4 for all rows where the partition is 2019 and id is 2. UPDATE acid_update_pt SET id = 4 WHERE ds = '2019' AND id = 2; -- View the update result. 2 has been updated to 4. SELECT * FROM acid_update_pt WHERE ds = '2019'; -- The following result is returned: +------------+------------+ | id | ds | +------------+------------+ | 4 | 2019 | | 1 | 2019 | | 3 | 2019 | +------------+------------+ -
Exemple 3 : créez une table cible nommée acid_update_t et une table associée nommée acid_update_s pour mettre à jour plusieurs valeurs de colonne simultanément. Voici les commandes d'exemple :
-- Create a target Transactional table to be updated, named acid_update_t, and an associated table named acid_update_s. CREATE TABLE IF NOT EXISTS acid_update_t(id INT,value1 INT,value2 INT) tblproperties ("transactional"="true"); CREATE TABLE IF NOT EXISTS acid_update_s(id INT,value1 INT,value2 INT); -- Insert data. INSERT OVERWRITE TABLE acid_update_t VALUES(2,20,21),(3,30,31),(4,40,41); INSERT OVERWRITE TABLE acid_update_s VALUES(1,100,101),(2,200,201),(3,300,301); -- Method 1: Update with constants. UPDATE acid_update_t SET (value1, value2) = (60,61); -- Query the result data in the target table for Method 1. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 60 | 61 | | 3 | 60 | 61 | | 4 | 60 | 61 | +------------+------------+------------+ -- Method 2: Join update. The rule is a left join from acid_update_t to acid_update_s. UPDATE acid_update_t SET (value1, value2) = (SELECT value1, value2 FROM acid_update_s WHERE acid_update_t.id = acid_update_s.id); -- Query the result data in the target table for Method 2. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 200 | 201 | | 3 | 300 | 301 | | 4 | NULL | NULL | +------------+------------+------------+ -- Method 3 (update based on the result of Method 2): Join update. The rule is to add a filter condition to update only the intersection. UPDATE acid_update_t SET (value1, value2) = (SELECT value1, value2 FROM acid_update_s WHERE acid_update_t.id = acid_update_s.id) WHERE acid_update_t.id IN (SELECT id FROM acid_update_s); -- Query the result data in the target table for Method 3. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 200 | 201 | | 3 | 300 | 301 | | 4 | NULL | NULL | +------------+------------+------------+ -- Method 4 (update based on the result of Method 3): Join update with aggregate results. UPDATE acid_update_t SET (id, value1, value2) = (SELECT id, MAX(value1),MAX(value2) FROM acid_update_s WHERE acid_update_t.id = acid_update_s.id GROUP BY acid_update_s.id) WHERE acid_update_t.id IN (SELECT id FROM acid_update_s); -- Query the result data in the target table for Method 4. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 200 | 201 | | 3 | 300 | 301 | | 4 | NULL | NULL | +------------+------------+------------+ -
Exemple 4 : requête de jointure simple impliquant deux tables. Voici les commandes d'exemple :
-- Create a target table for update, acid_update_t, and an associated table, acid_update_s. CREATE TABLE IF NOT EXISTS acid_update_t(id BIGINT,value1 BIGINT,value2 BIGINT) tblproperties ("transactional"="true"); CREATE TABLE IF NOT EXISTS acid_update_s(id BIGINT,value1 BIGINT,value2 BIGINT); -- Insert data. INSERT OVERWRITE TABLE acid_update_t VALUES(2,20,21),(3,30,31),(4,40,41); INSERT OVERWRITE TABLE acid_update_s VALUES(1,100,101),(2,200,201),(3,300,301); -- Query data from the acid_update_t table. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 20 | 21 | | 3 | 30 | 31 | | 4 | 40 | 41 | +------------+------------+------------+ -- Query data from the acid_update_s table. SELECT * FROM acid_update_s; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 1 | 100 | 101 | | 2 | 200 | 201 | | 3 | 300 | 301 | +------------+------------+------------+ -- Join update. Add a filter condition to the target table to update only the intersection. UPDATE acid_update_t SET value1 = b.value1, value2 = b.value2 FROM acid_update_s b WHERE acid_update_t.id = b.id; -- The following command is equivalent to the one above. UPDATE acid_update_t a SET a.value1 = b.value1, a.value2 = b.value2 FROM acid_update_s b WHERE a.id = b.id; -- View the update result. 20 is updated to 200, 21 to 201, 30 to 300, and 31 to 301. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 4 | 40 | 41 | | 2 | 200 | 201 | | 3 | 300 | 301 | +------------+------------+------------+ -
Exemple 5 : requête de jointure complexe impliquant plusieurs tables. Voici les commandes d'exemple :
-- Create a target table for update, acid_update_t, and an associated table, acid_update_s. CREATE TABLE IF NOT EXISTS acid_update_t(id BIGINT,value1 BIGINT,value2 BIGINT) tblproperties ("transactional"="true"); CREATE TABLE IF NOT EXISTS acid_update_s(id BIGINT,value1 BIGINT,value2 BIGINT); CREATE TABLE IF NOT EXISTS acid_update_m(id BIGINT,value1 BIGINT,value2 BIGINT); -- Insert data. INSERT OVERWRITE TABLE acid_update_t VALUES(2,20,21),(3,30,31),(4,40,41),(5,50,51); INSERT OVERWRITE TABLE acid_update_s VALUES (1,100,101),(2,200,201),(3,300,301),(4,400,401),(5,500,501); INSERT OVERWRITE TABLE acid_update_m VALUES(3,30,101),(4,400,201),(5,300,301); -- Query data from the acid_update_t table. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 2 | 20 | 21 | | 3 | 30 | 31 | | 4 | 40 | 41 | | 5 | 50 | 51 | +------------+------------+------------+ -- Query data from the acid_update_s table. SELECT * FROM acid_update_s; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 1 | 100 | 101 | | 2 | 200 | 201 | | 3 | 300 | 301 | | 4 | 400 | 401 | | 5 | 500 | 501 | +------------+------------+------------+ -- Query data from the acid_update_m table. SELECT * FROM acid_update_m; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 3 | 30 | 101 | | 4 | 400 | 201 | | 5 | 300 | 301 | +------------+------------+------------+ -- Join update, and filter both the source and target tables in the WHERE clause. UPDATE acid_update_t SET value1 = acid_update_s.value1, value2 = acid_update_s.value2 FROM acid_update_s WHERE acid_update_t.id = acid_update_s.id AND acid_update_s.id > 2 AND acid_update_t.value1 NOT IN (SELECT value1 FROM acid_update_m WHERE id = acid_update_t.id) AND acid_update_s.value1 NOT IN (SELECT value1 FROM acid_update_m WHERE id = acid_update_s.id); -- View the update result. Only the data in the acid_update_t table with id 5 meets the condition. The corresponding value1 is updated to 500, and value2 is updated to 501. SELECT * FROM acid_update_t; -- The following result is returned: +------------+------------+------------+ | id | value1 | value2 | +------------+------------+------------+ | 5 | 500 | 501 | | 2 | 20 | 21 | | 3 | 30 | 31 | | 4 | 40 | 41 | +------------+------------+------------+ -
Exemple 6 : la commande suivante illustre comment créer une Delta Table nommée mf_dt, importer des données et exécuter une opération
UPDATEpour supprimer les lignes répondant à une condition spécifiée :-- Create a target Delta Table named mf_dt. CREATE TABLE IF NOT EXISTS mf_dt (pk BIGINT NOT NULL PRIMARY KEY, val BIGINT NOT NULL) PARTITIONED BY(dd STRING, hh STRING) tblproperties ("transactional"="true"); -- Insert data. INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='02') VALUES (1, 1), (2, 2), (3, 3); -- View the inserted data. SELECT * FROM mf_dt WHERE dd='01' AND hh='02'; -- The following result is returned: +------------+------------+----+----+ | pk | val | dd | hh | +------------+------------+----+----+ | 1 | 1 | 01 | 02 | | 3 | 3 | 01 | 02 | | 2 | 2 | 01 | 02 | +------------+------------+----+----+ -- Update a column in a specified row. Set the val value to 30 for all rows where the partition is 01 and 02, and pk is 3. -- Method 1 UPDATE mf_dt SET val = 30 WHERE pk = 3 AND dd='01' AND hh='02'; -- Method 2 UPDATE mf_dt SET val = delta.val FROM (SELECT pk, val FROM VALUES (3, 30) t (pk, val)) delta WHERE delta.pk = mf_dt.pk AND mf_dt.dd='01' AND mf_dt.hh='02'; -- View the update result. SELECT * FROM mf_dt WHERE dd='01' AND hh='02'; -- The following result is returned. The val value for the row with pk=3 is updated to 30. +------------+------------+----+----+ | pk | val | dd | hh | +------------+------------+----+----+ | 1 | 1 | 01 | 02 | | 3 | 30 | 01 | 02 | | 2 | 2 | 01 | 02 | +------------+------------+----+----+
-
Fusionner les fichiers de table transactionnelle
Le stockage physique sous-jacent d'une table transactionnelle est composé de fichiers de base et de fichiers Delta, qui ne sont pas directement lisibles. Lorsque vous exécutez une opération UPDATE ou DELETE sur une table transactionnelle, les fichiers de base ne sont pas modifiés. À la place, des fichiers Delta sont ajoutés. Cela signifie que plus vous effectuez de mises à jour ou de suppressions, plus la table occupe d'espace de stockage. L'accumulation de nombreux fichiers Delta peut augmenter le stockage et les coûts des requêtes ultérieures.
L'exécution de plusieurs opérations UPDATE ou DELETE sur la même table ou partition génère de nombreux fichiers Delta. Lorsque le système lit les données, il doit charger ces fichiers Delta pour déterminer quelles lignes ont été mises à jour ou supprimées. La présence de nombreux fichiers Delta peut dégrader les performances de lecture des données. Dans ce cas, vous pouvez fusionner les fichiers de base et les fichiers Delta pour réduire le stockage et améliorer les performances de lecture des données.
-
Syntaxe
ALTER TABLE <table_name> [PARTITION (<partition_key> = '<partition_value>' [, ...])] compact {minor|major}; -
Paramètres
Paramètre
Obligatoire
Description
table_name
Oui
Nom de la table transactionnelle dont vous souhaitez fusionner les fichiers.
partition_key
Non
Si la table transactionnelle est une table partitionnée, spécifiez le nom de la colonne de clé de partition.
partition_value
Non
Si la table transactionnelle est une table partitionnée, spécifiez la valeur de la colonne de clé de partition.
major|minor
Oui
Vous devez en choisir un. Les différences sont les suivantes :
minor: fusionne uniquement les fichiers de base et tous leurs fichiers Delta sous-jacents, en éliminant les fichiers Delta.major: non seulement fusionne les fichiers de base et tous leurs fichiers Delta sous-jacents pour éliminer les fichiers Delta, mais fusionne également les petits fichiers au sein des fichiers de base correspondants de la table. Si un fichier de base est petit (inférieur à 32 Mo) ou si des fichiers Delta existent, cela équivaut à exécuter à nouveau une opérationINSERT OVERWRITEsur la table. Cependant, si le fichier de base est suffisamment grand (supérieur ou égal à 32 Mo) et qu'aucun fichier Delta n'existe, il ne sera pas réécrit. -
Précautions
Les petits fichiers fusionnés par l'opération
compactsont supprimés après un jour. Si vous utilisez la fonctionnalité sauvegarde locale pour restaurer un historique dépendant de ces petits fichiers, la récupération échouera car les fichiers seront manquants. -
Exemples
-
Exemple 1 : fusionner les fichiers de la table transactionnelle acid_delete. Voici la commande d'exemple :
ALTER TABLE acid_delete compact minor;Le résultat suivant est renvoyé :
Summary: Nothing found to merge, set odps.merge.cross.paths=true if cross path merge is permitted. OK -
Exemple 2 : fusionner les fichiers de la table transactionnelle acid_update_pt. Voici la commande d'exemple :
ALTER TABLE acid_update_pt PARTITION (ds = '2019') compact major;Le résultat suivant est renvoyé :
Summary: table name: acid_update_pt /ds=2019 instance count: 2 run time: 6 before merge, file count: 8 file size: 2613 file physical size: 7839 after merge, file count: 2 file size: 679 file physical size: 2037 OK
-
FAQ
-
Problème 1 :
Description du problème : lors de l'exécution d'une instruction
UPDATE, l'erreurODPS-0010000:System internal error - fuxi job failed, caused by: Data Set should contain exactly one rowest signalée.-
Cause : les lignes à mettre à jour ne correspondent pas bijectivement aux données du résultat de la sous-requête. Le système ne peut pas déterminer quelle ligne mettre à jour. Voici une commande d'exemple :
UPDATE store SET (s_county, s_manager) = (SELECT d_country, d_manager FROM store_delta sd WHERE sd.s_store_sk = store.s_store_sk) WHERE s_store_sk IN (SELECT s_store_sk FROM store_delta);La sous-requête
SELECT d_country, d_manager FROM store_delta sd WHERE sd.s_store_sk = store.s_store_sksert à effectuer une jointure avec store_delta, et les données de store_delta sont utilisées pour mettre à jour store. Supposons que la colonne s_store_sk de la table store contienne trois lignes de données :[1, 2, 3]. Si la colonne s_store_sk de la table store_delta comporte deux lignes de données,[1, 1], aucune correspondance bijective n'existe et l'exécution échoue. Solution : assurez-vous que les lignes à mettre à jour correspondent bijectivement aux données du résultat de la sous-requête.
-
Problème 2 :
Description du problème : lors de l'exécution de la commande
compactdans DataWorks DataStudio, l'erreurODPS-0130161:[1,39] Parse exception - invalid token 'minor', expect one of 'StringLiteral','DoubleQuoteStringLiteral'est signalée.Cause : la version du client MaxCompute dans le groupe de ressources exclusives pour DataWorks ne prend pas en charge la commande
compact.Solution : contactez l'équipe d'assistance technique via le groupe DingTalk DataWorks pour mettre à niveau la version du client MaxCompute dans le groupe de ressources exclusives.