ApsaraDB for SelectDB prend en charge la syntaxe SQL standard, notamment les instructions INSERT INTO pour l'importation de données dans des tables SelectDB. Utilisez INSERT INTO...SELECT pour exécuter des opérations ETL sur des tables internes ou synchroniser des données depuis des lacs de données externes, et réservez INSERT INTO...VALUES aux tests et à la validation uniquement.
Cas d'utilisation d'INSERT INTO
INSERT INTO se décline en deux variantes. Choisissez celle qui correspond à votre scénario :
| Variante | À utiliser lorsque | À éviter lorsque |
|---|---|---|
INSERT INTO...SELECT |
Vous exécutez des opérations ETL sur des tables internes ou synchronisez des données depuis des lacs de données externes via un catalog | — |
INSERT INTO...VALUES |
Vous effectuez des tests et des validations | Vous travaillez dans des environnements de production ou traitez de gros volumes de données |
Le débit d'écriture de INSERT INTO...VALUES est faible. Pour les charges de travail de production impliquant des écritures fréquentes mais de faible volume, privilégiez Stream Load, qui offre des performances d'écriture nettement supérieures.
Fonctionnement
Les deux variantes sont synchrones : l'instruction ne retourne un résultat qu'une fois l'importation terminée. Chaque importation crée une transaction identifiée par un libellé unique. Le résultat comprend ce libellé, l'ID de transaction ainsi que l'état de visibilité des données.
Prérequis
Avant de commencer, assurez-vous de disposer des éléments suivants :
Une instance ApsaraDB for SelectDB
Une table de destination dans SelectDB
Les permissions d'écriture sur la table de destination
Instruction INSERT INTO...SELECT
Cette variante permet d'exécuter des opérations d'extraction, de transformation et de chargement (ETL) sur des données déjà présentes dans SelectDB, ou de synchroniser des données provenant de sources externes via un catalog.
Exécuter une opération ETL sur une table interne
Pour transformer des données issues d'une table SelectDB et écrire les résultats dans une autre table :
INSERT INTO bj_store_sales
SELECT id, total, user_id, sale_timestamp FROM store_sales WHERE region = "bj";
Cette commande lit les lignes de store_sales où region = "bj" et les écrit dans bj_store_sales.
Synchroniser des données depuis un lac de données
Les catalogs SelectDB permettent de mapper des sources de données externes (Hive, Iceberg, Hudi, Elasticsearch et sources Java Database Connectivity (JDBC)) et de les interroger via des requêtes fédérées. Utilisez un catalog pour synchroniser les données d'un lac de données vers une table SelectDB.
L'exemple suivant illustre la synchronisation de données depuis une source Hive vers SelectDB.
Connectez-vous à votre instance SelectDB. Pour plus de détails, consultez Se connecter à une instance ApsaraDB for SelectDB à l'aide d'un client MySQL.
Créez un catalog pour intégrer la source de données Hive. Pour plus de détails, consultez Source de données Hive.
-
(Facultatif) Créez une base de données de destination. Ignorez cette étape si la base de données existe déjà.
CREATE DATABASE hive_db; -
Basculez vers la base de données de destination.
USE hive_db; -
Créez une table de destination. Si la table existe déjà, vérifiez que ses types de colonnes correspondent à ceux de la table source. Pour le référentiel de mappage des types, consultez Mappages des types de données de colonne.
CREATE TABLE test_Hive2SelectDB ( id int, name varchar(50), age int ) DISTRIBUTED BY HASH(id) BUCKETS 4 PROPERTIES("replication_num" = "1"); -
(Facultatif) Prévisualisez la table avant l'importation.
SELECT * FROM test_Hive2SelectDB;
-
Exécutez l'instruction INSERT INTO...SELECT pour synchroniser les données. Attribuez un libellé unique à la tâche d'importation avec
WITH LABEL.INSERT INTO test_Hive2SelectDB WITH LABEL test_label SELECT * FROM hive_catalog.testdb.hive_t; -
Interrogez la table de destination pour vérifier les données. Les données de la table de destination apparaissent à gauche et celles de la source à droite.

Instruction INSERT INTO...VALUES
Réservez cette variante aux tests et à la validation ; ne l'utilisez pas en production. Envoyez les requêtes d'insertion via un client SQL ou une application JDBC.
Commencez par créer une table de destination :
CREATE TABLE test_table
(
id int,
name varchar(50),
age int
)
DISTRIBUTED BY HASH(id) BUCKETS 4
PROPERTIES("replication_num" = "1");
Utilisation d'un client SQL
Regroupez plusieurs instructions INSERT INTO dans une transaction afin de les traiter comme une seule importation par lot :
BEGIN;
INSERT INTO test_table VALUES (1, 'Zhang San', 32),(2, 'Li Si', 45),(3, 'Zhao Liu', 23);
INSERT INTO test_table VALUES (4, 'Wang Yi', 32),(5, 'Zhao Er', 45),(6, 'Li Er', 23);
INSERT INTO test_table VALUES (7, 'Li Yi', 32),(8, 'Wang San', 45),(9, 'Zhao Si', 23);
COMMIT;
Utilisation d'une application JDBC
L'exemple suivant regroupe plusieurs instructions INSERT INTO dans une seule transaction via JDBC. Remplacez les valeurs d'espace réservé par vos propres valeurs.
public static void main(String[] args) throws Exception {
// Number of INSERT statements per batch
int insertNum = 10;
// Number of rows per INSERT statement
int batchSize = 10000;
// Replace <host> and <port> with your VPC (virtual private cloud) endpoint values.
// Find these on the Instance Details page under Network Information.
String URL = "jdbc:mysql://<host>:<port>/test_db?useLocalSessionState=true";
Connection connection = DriverManager.getConnection(URL, "admin", "<password>");
Statement statement = connection.createStatement();
statement.execute("BEGIN;");
for (int num = 0; num < insertNum; num++) {
StringBuilder sql = new StringBuilder();
sql.append("INSERT INTO test_table VALUES ");
for (int i = 0; i < batchSize; i++) {
if (i > 0) {
sql.append(",");
}
// Replace with your actual field values
sql.append("(1, 'Zhang San', 32)");
}
statement.addBatch(sql.toString());
}
statement.addBatch("COMMIT;");
statement.executeBatch();
statement.close();
connection.close();
}
Comprendre le résultat de l'importation
INSERT INTO étant synchrone, examinez la valeur retournée pour déterminer le résultat de l'opération.
Importation réussie sans lignes
Si la clause SELECT ne retourne aucune ligne, SelectDB affiche :
INSERT INTO tbl1 SELECT * FROM empty_tbl;
Query OK, 0 rows affected (0.02 sec)
Query OK indique que l'instruction s'est exécutée sans erreur. 0 rows affected signifie qu'aucune donnée n'a été importée.
Importation réussie avec lignes
INSERT INTO tbl1 SELECT * FROM tbl2;
Query OK, 4 rows affected (0.38 sec)
{'label':'insert_8510c568-9eda-****-9e36-6adc7d35291c', 'status':'visible', 'txnId':'4005'}
La réponse JSON contient les informations suivantes :
| Champ | Description |
|---|---|
label |
Identifiant de la tâche d'importation : soit la valeur spécifiée avec WITH LABEL, soit une valeur générée automatiquement. Unique au sein d'une base de données. |
status |
Visibilité des données. visible indique que les données sont interrogeables. committed signifie que les données sont écrites mais pas encore visibles. |
txnId |
ID de transaction associé à cette importation. |
err |
Erreurs inattendues éventuelles. |
Si le status est committed, les données finiront par devenir visibles. Pour le vérifier :
SHOW TRANSACTION WHERE id=4005;
Si TransactionStatus affiche visible, les données sont interrogeables.
Importation réussie avec lignes filtrées
Si certaines lignes ont été filtrées, le résultat indique un nombre d'avertissements :
Query OK, 2 rows affected, 2 warnings (0.31 sec)
{'label':'insert_f0747f0e-7a35-****-affa-13a235f4020d', 'status':'visible', 'txnId':'4005'}
Pour examiner les lignes filtrées, recherchez le libellé dans la sortie de SHOW LOAD :
SHOW LOAD WHERE label="insert_f0747f0e-7a35-****-affa-13a235f4020d";
Ensuite, interrogez les détails de l'erreur à l'aide de l'URL fournie dans la sortie :
SHOW LOAD WARNINGS ON "<error-url>";
Échec de l'importation
En cas d'échec de l'importation, aucune donnée n'est écrite et SelectDB retourne une erreur :
INSERT INTO tbl1 SELECT * FROM tbl2 WHERE k1 = "a";
ERROR 1064 (HY000): all partitions have no load data. url: http://10.74.167.16:8042/api/_load_error_log?file=__shard_2/error_log_insert_stmt_ba8bb9e158e4879-ae8de8507c0bf8a2_ba8bb9e158e4879_ae8de8507c0bf8a2
Récupérez les informations détaillées sur l'erreur en utilisant l'URL présente dans le message d'erreur :
SHOW LOAD WARNINGS ON "<error-url>";
Référence de configuration
Variables de session
| Variable | Valeur par défaut | Description |
|---|---|---|
query_timeout |
300 s (5 min) | Délai d'attente pour l'opération INSERT INTO. Si l'importation ne se termine pas dans ce laps de temps, SelectDB l'annule. |
enable_insert_strict |
true |
Lorsque la valeur est true, l'importation échoue si des lignes sont filtrées. Avec false, les lignes filtrées sont ignorées silencieusement. |
enable_unique_key_partial_update |
false |
Définie sur true, cette variable active les mises à jour partielles de colonnes sur les tables du modèle Unique Key utilisant Merge on Write (MOW). |
Mises à jour partielles de colonnes
Par défaut, INSERT INTO écrit des lignes complètes. Pour mettre à jour uniquement des colonnes spécifiques sur une table du modèle Unique Key utilisant Merge on Write (MOW) :
SET enable_unique_key_partial_update = true;
Cette variable s'applique uniquement aux tables utilisant le modèle Unique Key en mode Merge on Write (MOW).
Si
enable_unique_key_partial_updateetenable_insert_strictsont toutes deux définies surtrue, INSERT INTO ne peut mettre à jour que des lignes existantes. Une erreur est retournée si une clé n'existe pas dans la table.Pour mettre à jour des colonnes existantes tout en insérant de nouvelles lignes, définissez
enable_unique_key_partial_update = trueetenable_insert_strict = false. Pour plus de détails, consultez Configurer les variables.
Pour obtenir la liste complète des variables, consultez Gestion des variables.
Bonnes pratiques
Évitez les écritures fréquentes de petit volume. Des insertions trop rapprochées dégradent les performances et peuvent provoquer des interblocages sur les tables. Maintenez un intervalle d'au moins 10 secondes entre les écritures sur une même table et regroupez plusieurs lignes dans une seule instruction INSERT INTO.
Taille de lot pour INSERT INTO...VALUES. Pour des performances optimales, regroupez entre 1 000 et 1 000 000 de lignes par instruction.
Privilégiez Stream Load pour l'ingestion en production. Dans les environnements de production et pour les gros volumes de données, utilisez Stream Load plutôt que INSERT INTO...VALUES.
Attribuez des libellés pour assurer la traçabilité. Utilisez WITH LABEL pour assigner des libellés explicites aux tâches d'importation, ce qui facilite la consultation de leur état et le débogage des erreurs. Si vous souhaitez utiliser des expressions de table communes (CTE) pour définir des sous-requêtes dans une instruction INSERT INTO, vous devez spécifier WITH LABEL et column.
Seuil de filtrage. INSERT INTO ne prend pas en charge le paramètre max_filter_ratio. Par défaut, toutes les lignes erronées sont ignorées (équivalent à max_filter_ratio = 1). Pour appliquer une tolérance zéro aux erreurs de données, définissez enable_insert_strict = true.
FAQ
Pourquoi l'erreur get table cloud commit lock timeout apparaît-elle lors de l'importation ?
Ce problème survient lorsque les écritures sur une même table sont trop fréquentes, entraînant une contention des verrous. Réduisez la fréquence d'écriture afin que chaque table ne reçoive des écritures qu'une fois toutes les 5 secondes au maximum, et consolidez plusieurs petites insertions en lots plus importants et moins nombreux.
Étapes suivantes
Stream Load : ingestion à haut débit pour les cas d'utilisation en production
Data lakehouse : intégration de sources de données externes avec SelectDB
Gestion des variables : configuration des variables de session pour le comportement d'INSERT INTO