MaxCompute vous permet d'utiliser INSERT INTO ou INSERT OVERWRITE pour insérer ou écraser des données dans une table cible ou une partition statique.
Vous pouvez exécuter les commandes présentées dans cette rubrique sur les plateformes suivantes :
Prérequis
Pour effectuer des opérations INSERT INTO et INSERT OVERWRITE, vous devez disposer de l'autorisation Update sur la table cible et de l'autorisation Select sur la table source. Pour plus d'informations sur l'octroi des autorisations, consultez la rubrique Autorisations MaxCompute.
Présentation
Lors du traitement des données avec MaxCompute SQL, vous pouvez utiliser l'instruction INSERT INTO ou INSERT OVERWRITE pour enregistrer le résultat d'une requête SELECT dans une table cible. Les différences sont les suivantes :
INSERT INTO: ajoute des données à une table ou à une partition statique. Vous pouvez spécifier les valeurs de partition dans l'instructionINSERTpour insérer des données dans une partition spécifique. Pour insérer une petite quantité de données de test, vous pouvez utiliser cette instruction avec VALUES.-
INSERT OVERWRITE: efface les données existantes dans une table ou une partition statique avant d'insérer les nouvelles données.RemarqueLa syntaxe
INSERTde MaxCompute diffère de la syntaxeINSERTde MySQL ou Oracle. Vous pouvez omettre le mot-cléTABLEdans les instructionsINSERT INTOetINSERT OVERWRITE.Lorsque vous effectuez plusieurs fois une opération
INSERT OVERWRITEsur la même partition, la valeurSizerenvoyée par la commandeDESCpeut varier. En effet, lorsque vousSELECTdes données depuis une partition puis utilisezINSERT OVERWRITEpour les réécrire dans la même partition, la logique de fractionnement des fichiers change. Par conséquent, laSizedes données évolue également. La longueur totale des données reste identique avant et après l'opérationINSERT OVERWRITEet aucun frais de stockage supplémentaire n'est engagé.
Pour savoir comment insérer des données dans des partitions dynamiques, consultez la rubrique Insérer ou écraser des données dans des partitions dynamiques (DYNAMIC PARTITION).
Limites
-
Les limites suivantes s'appliquent lorsque vous utilisez
INSERT INTOetINSERT OVERWRITEpour mettre à jour des données dans une table ou une partition statique :INSERT INTO: vous ne pouvez pas ajouter de données à une table clusterisée.INSERT OVERWRITE: ne prend pas en charge la spécification des colonnes pour l'insertion. Pour spécifier des colonnes, utilisezINSERT INTO. Par exemple, l'instructionCREATE TABLE t(a STRING, b STRING); INSERT INTO t(a) VALUES ('1');insère '1' dans la colonne a et définit la colonne b sur NULL ou sa valeur par défaut.MaxCompute n'implémente pas de verrous de table. N'effectuez pas simultanément des opérations
INSERT INTOouINSERT OVERWRITEsur la même table.
-
Les limites suivantes s'appliquent à une Delta Table.
Lorsque vous utilisez
INSERT OVERWRITEpour écrire des données dans une Delta Table, les lignes multiples ayant la même valeur de clé primaire (PK) sont dédupliquées avant l'écriture. Seule la première ligne est écrite. Le résultat final dépend de l'ordre des enregistrements lors du processus de calcul, qui ne peut pas être spécifié manuellement. Comme cette opération écrit l'ensemble des données, cette déduplication par défaut permet de garantir l'unicité de la clé primaire.Lorsque vous écrivez des données dans une Delta Table en utilisant
INSERT INTO, les lignes multiples ayant la même valeur de clé primaire (PK) ne sont pas dédupliquées par défaut et toutes sont écrites dans la table. Toutefois, si vous définissezset odps.sql.insert.acidtable.deduplicate.enable = true, les données sont dédupliquées avant d'être écrites dans la table.
Syntaxe
INSERT {INTO|OVERWRITE} TABLE <table_name> [PARTITION (<pt_spec>)] [(<col_name> [,<col_name> ...)]]
<select_statement>
FROM <from_statement>
[ZORDER BY <zcol_name> [, <zcol_name> ...]];
Le tableau suivant décrit les paramètres.
Paramètre | Obligatoire | Description |
table_name | Oui | Nom de la table cible dans laquelle vous souhaitez insérer des données. |
pt_spec | Non | Partition dans laquelle insérer les données. Vous devez spécifier une constante. Les fonctions et expressions ne sont pas autorisées. Le format est |
col_name | Non | Nom de la colonne de la table cible dans laquelle vous souhaitez insérer des données.
|
select_statement | Oui | Clause Remarque
|
from_statement | Oui | Clause |
ZORDER BY <zcol_name> [, <zcol_name> ...] | Non | Lors de l'écriture de données dans une table ou une partition, vous pouvez trier les données selon une ou plusieurs colonnes spécifiées (colonnes de la table correspondant à select_statement) afin de regrouper les lignes contenant des données similaires. Cela améliore les performances de filtrage des requêtes et peut réduire les coûts de stockage. Notez que |
Les différences entre ZORDER BY et SORT BY sont les suivantes :
-
ZORDER BYdispose de deux modes : local zorder et global zorder. Le mode par défaut estlocal zorder. Le mode local trie les données par ordre Z uniquement au sein de fichiers individuels et ne redistribue pas les données globalement. Par conséquent, si les données sont réparties sur plusieurs fichiers, le regroupement des données peut être faible, ce qui empêche un Data Skipping efficace. Pour résoudre ce problème, les versions plus récentes prennent en chargeglobal zorder. Pour utiliser le modeglobal zorder, définissez le paramètre suivant :SET odps.sql.default.zorder.type=global;.ZORDER BYprésente les limites suivantes :Pour les tables partitionnées, vous ne pouvez effectuer un tri
ZORDER BYque sur une seule partition à la fois.Le nombre de colonnes
ZORDER BYdoit être compris entre 2 et 4.Lorsque la table cible est une table clusterisée, la clause
ZORDER BYn'est pas prise en charge.ZORDER BYpeut être utilisé avecDISTRIBUTE BY, mais ne peut pas être utilisé avecORDER BY,CLUSTER BYniSORT BY.
RemarqueLorsque vous écrivez des données en utilisant la clause
ZORDER BY, l'opération consomme plus de ressources et prend plus de temps que sans tri. L'instruction
SORT BYsert à spécifier comment les données sont triées au sein d'un fichier unique. Si vous ne spécifiez pasSORT BY, les données au sein d'un fichier unique sont triées parlocal zorder.
Exemples : tables classiques
-
Exemple 1 : exécutez la commande
INSERT INTOpour ajouter des données à la table non partitionnéewebsites. La commande est la suivante :--Create a non-partitioned table named websites. CREATE TABLE IF NOT EXISTS websites (id INT, name STRING, url STRING ); --Create a non-partitioned table named apps. CREATE TABLE IF NOT EXISTS apps (id INT, app_name STRING, url STRING ); --Append data to the apps table. The keyword TABLE in `INSERT INTO TABLE ` is optional. INSERT INTO apps (id,app_name,url) VALUES (1,'Aliyun','https://www.aliyun.com'); --Copy data from the apps table and append it to the websites table. INSERT INTO websites (id,name,url) SELECT id,app_name,url FROM apps; --Run the SELECT statement to view the data in the websites table. SELECT * FROM websites;Le résultat suivant est renvoyé :
-- The result. +------------+------------+------------+ | id | name | url | +------------+------------+------------+ | 1 | Aliyun | https://www.aliyun.com | +------------+------------+------------+ -
Exemple 2 : exécutez la commande
INSERT INTOpour ajouter des données à la table partitionnéesale_detail. Voici un exemple de commande :-- Create a partitioned table named sale_detail. CREATE TABLE IF NOT EXISTS sale_detail ( shop_name STRING, customer_id STRING, total_price DOUBLE ) PARTITIONED BY (sale_date STRING, region STRING); -- Add a partition to the source table. This step is optional. If the partition does not exist, it is automatically created when you write data. ALTER TABLE sale_detail ADD PARTITION (sale_date='2013', region='china'); -- Append data to the source table. The TABLE keyword after INSERT INTO and INSERT OVERWRITE is optional. INSERT INTO sale_detail PARTITION (sale_date='2013', region='china') VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3); -- Enable a full table scan for the current session only. Run a SELECT statement to view data in the sale_detail table. SET odps.sql.allow.fullscan=true; SELECT * FROM sale_detail;Le résultat suivant est renvoyé :
+------------+-------------+-------------+------------+------------+ | shop_name | customer_id | total_price | sale_date | region | +------------+-------------+-------------+------------+------------+ | s1 | c1 | 100.1 | 2013 | china | | s2 | c2 | 100.2 | 2013 | china | | s3 | c3 | 100.3 | 2013 | china | +------------+-------------+-------------+------------+------------+ -
Exemple 3 : exécutez la commande
INSERT OVERWRITEpour écraser les données de la tablesale_detail_insert. Voici un exemple de commande :-- Create a target table named sale_detail_insert with the same schema as sale_detail. CREATE TABLE sale_detail_insert LIKE sale_detail; -- Add a partition to the target table. This step is optional. If the partition does not exist, it is automatically created when you write data. ALTER TABLE sale_detail_insert ADD PARTITION (sale_date='2013', region='china'); -- Overwrite a static partition. For static partitions, partition columns are specified in the PARTITION() clause and must not be in the SELECT list. The columns in the SELECT list are mapped to the target table's columns by position. SET odps.sql.allow.fullscan=true; INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date='2013', region='china') SELECT shop_name, customer_id, total_price FROM sale_detail ZORDER BY customer_id, total_price; -- Enable a full table scan for the current session only. Run a SELECT statement to view data in the sale_detail_insert table. SET odps.sql.allow.fullscan=true; SELECT * FROM sale_detail_insert;Le résultat suivant est renvoyé :
+------------+-------------+-------------+------------+------------+ | shop_name | customer_id | total_price | sale_date | region | +------------+-------------+-------------+------------+------------+ | s1 | c1 | 100.1 | 2013 | china | | s2 | c2 | 100.2 | 2013 | china | | s3 | c3 | 100.3 | 2013 | china | +------------+-------------+-------------+------------+------------+ -
Exemple 4 : exécutez la commande
INSERT OVERWRITEpour écraser les données de la tablesale_detail_insertet modifier l'ordre des colonnes dans la clauseSELECT. Le mappage entre la table source et la table cible repose sur l'ordre des colonnes dans la clauseSELECT, et non sur les noms de colonnes. La commande est la suivante :SET odps.sql.allow.fullscan=true; INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date='2013', region='china') SELECT customer_id, shop_name, total_price FROM sale_detail; SET odps.sql.allow.fullscan=true; SELECT * FROM sale_detail_insert;Le résultat suivant est renvoyé :
+------------+-------------+-------------+------------+------------+ | shop_name | customer_id | total_price | sale_date | region | +------------+-------------+-------------+------------+------------+ | c1 | s1 | 100.1 | 2013 | china | | c2 | s2 | 100.2 | 2013 | china | | c3 | s3 | 100.3 | 2013 | china | +------------+-------------+-------------+------------+------------+Lors de la création de la table
sale_detail_insert, l'ordre des colonnes était le suivant :+-------------------+--------------------+-------------------+ | shop_name STREING | customer_id STRING| total_price BIGINT| +-------------------+--------------------+-------------------+L'ordre d'insertion des données de
sale_detaildanssale_detail_insertest le suivant :+---------------------+--------------------+-------------------+ | customer_id STRING | shop_name STREING | total_price BIGINT| +---------------------+--------------------+-------------------+Dans ce cas, les données de
sale_detail.customer_idsont insérées danssale_detail_insert.shop_name, et les données desale_detail.shop_namesont insérées danssale_detail_insert.customer_id. -
Exemple 5 : lors de l'insertion de données dans une partition, les colonnes de partition ne peuvent pas apparaître dans la clause
SELECT. L'instruction suivante renvoie une erreur carsale_dateetregionsont des colonnes de partition, ce qui n'est pas autorisé dans la clauseSELECTpour une partition statique. Voici un exemple de commande incorrecte :INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date='2013', region='china') SELECT shop_name, customer_id, total_price, sale_date, region FROM sale_detail; -
Exemple 6 : la valeur de
PARTITIONne peut être qu'une constante, pas une expression. Voici un exemple de commande incorrecte :INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date=datepart('2016-09-18 01:10:00', 'yyyy') , region='china') SELECT shop_name, customer_id, total_price FROM sale_detail; -
Exemple 7 : exécutez la commande
INSERT OVERWRITEpour écraser les données des tablesmf_srcetmf_zorder_src, et triez la tablemf_zorder_srcen mode global zorder. Voici un exemple de commande :-- Create the target table mf_src. CREATE TABLE mf_src (key STRING, value STRING); INSERT OVERWRITE TABLE mf_src SELECT a, b FROM VALUES ('1', '1'),('3', '3'),('2', '2') AS t(a, b); SELECT * FROM mf_src; -- The result is returned: +-----+-------+ | key | value | +-----+-------+ | 1 | 1 | | 3 | 3 | | 2 | 2 | +-----+-------+ -- Create the target table mf_zorder_src with the same schema as mf_src. CREATE TABLE mf_zorder_src LIKE mf_src; -- Use the global z-order mode for sorting. SET odps.sql.default.zorder.type=global; INSERT OVERWRITE TABLE mf_zorder_src SELECT key, value FROM mf_src ZORDER BY key, value; SELECT * FROM mf_zorder_src;Le résultat suivant est renvoyé :
+-----+-------+ | key | value | +-----+-------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +-----+-------+ -
Exemple 8 : exécutez la commande
INSERT OVERWRITEpour écraser les données de la tabletargetexistante. La commande est la suivante :-- The 'target' table is an existing table. SET odps.sql.default.zorder.type=global; INSERT OVERWRITE TABLE target SELECT key, value FROM target ZORDER BY key, value;
Exemples : Delta Table
Exemple : créez la Delta Table mf_dt et exécutez la commande INSERT pour insérer et écraser des données.
-- Create a 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 test data into the partition where dd='01' and hh='01' in the mf_dt table.
INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='01')
VALUES (1, 1), (2, 2), (3, 3);
-- Query data in the target partition of the mf_dt table.
SELECT * FROM mf_dt WHERE dd='01' AND hh='01';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 1 | 01 | 01 |
| 3 | 3 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
-- Use 'INSERT INTO' to append data to the target partition of the mf_dt table.
INSERT INTO TABLE mf_dt PARTITION(dd='01', hh='01')
VALUES (3, 30), (4, 4), (5, 5);
SELECT * FROM mf_dt WHERE dd='01' AND hh='01';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 1 | 01 | 01 |
| 3 | 30 | 01 | 01 |
| 4 | 4 | 01 | 01 |
| 5 | 5 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
-- Use 'INSERT OVERWRITE' to overwrite data in the target partition of the mf_dt table.
INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='01')
VALUES (1, 1), (2, 2), (3, 3);
SELECT * FROM mf_dt WHERE dd='01' AND hh='01';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 1 | 01 | 01 |
| 3 | 3 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
-- Use 'INSERT OVERWRITE' to write data to the partition where dd='01' and hh='02' in the mf_dt table.
INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='02')
VALUES (1, 11), (2, 22), (3, 32);
SELECT * FROM mf_dt WHERE dd='01' AND hh='02';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 11 | 01 | 02 |
| 3 | 32 | 01 | 02 |
| 2 | 22 | 01 | 02 |
+------------+------------+----+----+
-- Enable a full table scan for the current session only. Run a SELECT statement to view data in the mf_dt table.
SET odps.sql.allow.fullscan=true;
SELECT * FROM mf_dt;
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 11 | 01 | 02 |
| 3 | 32 | 01 | 02 |
| 2 | 22 | 01 | 02 |
| 1 | 1 | 01 | 01 |
| 3 | 3 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
Bonnes pratiques
Le tri Z-order ne convient pas à tous les scénarios. Il peut être nécessaire de tester votre cas d'utilisation pour déterminer si les avantages en matière de stockage et de performances des requêtes justifient le coût de calcul supplémentaire lié à l'écriture de données triées par Z-order. Les sections suivantes fournissent des recommandations générales.
Privilégier un index clusterisé plutôt que Z-order
Si vos conditions de filtre reposent généralement sur un préfixe de colonnes, telles que
a,a and boua and b and c, l'utilisation d'un index clusterisé (par exemple,ORDER BY a, b, c) est plus efficace. N'utilisez pasZORDER BYdans ce cas. En effet,ORDER BYoffre un excellent tri pour la première colonne avec un impact moindre sur les colonnes suivantes. En revanche,ZORDER BYaccorde un poids égal à toutes les colonnes spécifiées, de sorte que le tri sur une seule colonne est moins efficace que le tri sur la première colonne d'une clauseORDER BY.Si certaines colonnes apparaissent fréquemment dans une clé
JOIN, le clustering Hash ou Range est plus approprié. L'implémentation Z-order de MaxCompute trie uniquement les données au sein des fichiers et le moteur SQL n'est pas conscient de la distribution des données Z-order. Cependant, le moteur SQL est conscient d'un index clusterisé et peut mieux optimiser les performances deJOINlors de la phase de planification de la requête.Si vous effectuez fréquemment des opérations
GROUP BYetORDER BYsur certaines colonnes, l'utilisation d'un index clusterisé peut offrir de meilleures performances.
Recommandations relatives à Z-order
Sélectionnez les colonnes qui apparaissent fréquemment dans les conditions de filtre, en particulier celles qui sont souvent filtrées conjointement.
Plus vous incluez de colonnes dans
ZORDER BY, moins le tri est efficace pour chaque colonne individuelle. Par conséquent, ne spécifiez pas plus de quatre colonnes. Si vous n'avez qu'une seule colonne, utilisez un index clusterisé plutôt que le tri Z-order.Sélectionnez des colonnes dont la cardinalité (nombre de valeurs distinctes) est équilibrée. Les colonnes à faible cardinalité, comme une colonne de genre, offrent un avantage de tri minimal. Les colonnes à haute cardinalité avec des valeurs majoritairement uniques augmentent les coûts de tri, car l'implémentation Z-order de MaxCompute doit mettre en cache toutes les valeurs distinctes en mémoire pour calculer la valeur Z.
La taille de la table ne doit être ni trop petite ni trop grande. Si le volume de données est trop faible, les avantages du tri Z-order ne sont pas apparents. Si le volume de données est trop important, le coût de génération des données triées par Z-order peut être élevé, ce qui peut avoir un impact significatif sur le temps d'achèvement des tâches de référence.