Les bases de données relationnelles traditionnelles exigent la définition préalable de chaque colonne avant l'écriture des données. L'ajout d'une colonne à une table volumineuse entraîne une modification du schéma longue et susceptible de bloquer vos activités. La fonctionnalité de colonnes dynamiques de LindormTable vous permet d'écrire des données dans des colonnes non définies dans le schéma de la table, sans aucune modification du schéma ni interruption de service.
Prérequis
Avant de commencer, assurez-vous que :
Votre instance LindormTable est en version 2.2.19 ou ultérieure. Pour mettre à niveau, consultez Mise à niveau de la version mineure du moteur d'une instance Lindorm
Vous savez que les colonnes dynamiques ne peuvent pas être désactivées une fois activées pour une table
Fonctionnement
Toutes les données stockées dans les colonnes dynamiques sont de type VARBINARY, qui représente des tableaux d'octets. Lors de l'écriture ou de l'interrogation de colonnes dynamiques via Lindorm-cli ou SQL, encodez les valeurs sous forme de chaînes hexadécimales (données binaires représentées par des caractères hexadécimaux 0–9 et A–F).
Une même table peut contenir des lignes avec différents ensembles de colonnes dynamiques. Par exemple, le tableau suivant présente trois lignes dont chacune possède un ensemble distinct de colonnes dynamiques :
+----+------+----------+
| p1 | c3 | c4 |
+----+------+----------+
| 1 | 0x41 | null |
| 2 | null | 0xef0011 |
| 3 | null | 0xef0011 |
+----+------+----------+
Si vous utilisez l'API HBase pour Java afin de créer une table ou d'écrire des données, vous pouvez également utiliser Lindorm SQL pour lire et écrire des colonnes dynamiques dans cette table.
Activer les colonnes dynamiques
Les colonnes dynamiques ne peuvent pas être désactivées une fois activées pour une table.
Activez les colonnes dynamiques à l'aide de l'une des méthodes suivantes :
-
Lors de la création de la table, en utilisant la clause
WITH:CREATE TABLE t_dynamic (p1 INT, c1 INT, c2 VARCHAR, PRIMARY KEY(p1)) WITH (DYNAMIC_COLUMNS='true'); -
Sur une table existante, en modifiant ses propriétés :
ALTER TABLE t_dynamic SET 'DYNAMIC_COLUMNS' = 'true';
Vérifier que les colonnes dynamiques sont activées
SHOW TABLE VARIABLES FROM t_dynamic LIKE 'DYNAMIC_COLUMNS';
Ajouter des colonnes prédéfinies après l'activation des colonnes dynamiques
Après avoir activé les colonnes dynamiques, vous pouvez toujours ajouter de nouvelles colonnes prédéfinies au schéma :
ALTER TABLE t_dynamic ADD COLUMN c3 int;
Si vous avez précédemment écrit des données dans une colonne dynamique nommée c3 (stockée en tant que VARBINARY), puis ajouté c3 en tant que colonne INT, les requêtes et insertions sur c3 en tant que INT échoueront en raison du conflit de type. Cette erreur ne se produit pas si vous ajoutez c3 avec le type VARBINARY. Ne réutilisez pas le nom d'une colonne dynamique existante lors de l'ajout de colonnes prédéfinies.
Écrire des données dans les colonnes dynamiques
Écriture à l'aide de paramètres SQL (recommandé)
Utilisez PreparedStatement avec setBytes() pour écrire directement des tableaux d'octets. Cela évite l'ambiguïté qui peut survenir lors du passage de chaînes hexadécimales en tant que simples chaînes, en particulier lorsque vous utilisez MySQL pour interagir avec Lindorm.
L'exemple Java (JDBC) suivant crée une table avec les colonnes dynamiques activées et insère une ligne où c2 est une colonne dynamique :
Connection conn = DriverManager.getConnection(lindorm-jdbc-url);
String createTable = "CREATE TABLE testTable (p1 VARCHAR, c1 INT, PRIMARY KEY(p1)) 'DYNAMIC_COLUMNS' = 'true'";
Statement statement = conn.createStatement();
statement.execute(createTable);
// Insert p1 and c1 (predefined) and c2 (dynamic column)
String sqlUpsert = "upsert into testTable (p1, c1, c2) values(?, ?, ?)";
try (PreparedStatement stmt = conn.prepareStatement(sqlUpsert)) {
stmt.setString(1, "pk");
stmt.setInt(2, 4);
stmt.setBytes(3, new byte[] {0, 1}); // Pass byte array directly
stmt.executeUpdate();
}
Ne passez pas de chaînes hexadécimales via setString() pour les colonnes dynamiques, en particulier lors de la connexion via MySQL. MySQL envoie les paramètres STRING sous forme de tableaux d'octets, ce qui peut entraîner une ambiguïté des données.
Écriture à l'aide d'instructions SQL (Lindorm-cli)
Passez les valeurs sous forme de chaînes hexadécimales dans les instructions UPSERT. Chaque chaîne hexadécimale représente un tableau d'octets, où chaque paire de chiffres hexadécimaux encode un octet.
Un octet peut être représenté par un nombre décimal compris entre 0 et 255, ou par deux chiffres hexadécimaux allant de 0x00 à 0xFF. Pour convertir un tableau d'octets en chaîne hexadécimale, consultez Conversion d'un tableau d'octets en chaîne hexadécimale.
Les exemples suivants utilisent la table t_dynamic (schéma : clé primaire p1 INT, c1 INT, c2 VARCHAR). Les colonnes c3, c4, c5 et c6 sont des colonnes dynamiques.
Écriture réussie — chaîne hexadécimale en tant que chaîne simple :
UPSERT INTO t_dynamic (p1, c2, c3) VALUES (1, '1', '41');
Écriture réussie — chaîne hexadécimale avec plusieurs octets :
UPSERT INTO t_dynamic (p1, c4) VALUES (2, 'ef0011');
Syntaxe recommandée dans Lindorm SQL 2.6.8 et versions ultérieures — utilisez le préfixe x'...' pour distinguer les chaînes hexadécimales des chaînes ordinaires :
UPSERT INTO t_dynamic (p1, c4) VALUES (3, x'ef0011');
Le littéral x'ef0011' écrit trois octets — 0xEF, 0x00 et 0x11 — et non la chaîne de six caractères ef0011.
Pour vérifier votre version de Lindorm SQL, consultez Versions SQL.
Échec de l'écriture — chaîne hexadécimale de longueur impaire :
UPSERT INTO t_dynamic (p1, c5) VALUES (4, 'f');
Cette opération échoue car f est un seul caractère hexadécimal. Les chaînes hexadécimales doivent comporter un nombre pair de caractères (chaque octet nécessite deux chiffres hexadécimaux). Utilisez plutôt 0f.
Échec de l'écriture — caractères hexadécimaux non valides :
UPSERT INTO t_dynamic (p1, c6) VALUES (5, x'gf');
Cette opération échoue car g n'est pas un caractère hexadécimal valide (valeurs valides : 0–9, A–F).
Interroger des données dans les colonnes dynamiques
La syntaxe de requête est identique à celle des tables classiques. Les exemples suivants interrogent la table t_dynamic après les opérations UPSERT ci-dessus.
Interroger des colonnes dynamiques spécifiques
Spécifiez explicitement les noms des colonnes dynamiques dans la clause SELECT :
SELECT p1, c2, c3, c4 FROM t_dynamic WHERE p1 = 1;
Résultat :
+----+----+------+------+
| p1 | c2 | c3 | c4 |
+----+----+------+------+
| 1 | 1 | 0x41 | null |
+----+----+------+------+
Découvrir toutes les colonnes dynamiques d'une table
Utilisez SELECT * avec une clause LIMIT pour récupérer toutes les colonnes, y compris les colonnes dynamiques. La clause LIMIT est requise pour garantir l'intégrité des métadonnées de l'ensemble de résultats. La valeur maximale par défaut de LIMIT est 5 000. Vous pouvez spécifier une valeur maximale. Si la valeur interrogée dépasse la valeur maximale, une erreur est renvoyée.
SELECT * FROM t_dynamic LIMIT 10;
Résultat :
+----+------+------+------+----------+
| p1 | c1 | c2 | c3 | c4 |
+----+------+------+------+----------+
| 1 | null | 1 | 0x41 | null |
| 2 | null | null | null | 0xef0011 |
| 3 | null | null | null | 0xef0011 |
+----+------+------+------+----------+
Utiliser des colonnes dynamiques dans les clauses WHERE
Incluez toujours la clé primaire ou une clé d'index dans la clause WHERE pour garantir les performances de la requête. Lors du filtrage sur les valeurs des colonnes dynamiques via Lindorm-cli ou SQL, utilisez des chaînes hexadécimales.
Requête réussie :
SELECT p1, c4 FROM t_dynamic WHERE p1 = 3 AND c4 = x'ef0011';
Échec de la requête — la valeur '1' n'est pas une chaîne hexadécimale :
SELECT p1, c1, c4 FROM t_dynamic WHERE p1 = 2 AND c4 = '1';
Afficher les données dans les colonnes dynamiques
Les résultats de requête pour les colonnes dynamiques s'affichent différemment selon l'outil client utilisé.
Outil en ligne de commande MySQL
L'outil en ligne de commande MySQL affiche par défaut les valeurs des colonnes dynamiques sous forme de points d'interrogation (?).
Conversion d'un tableau d'octets en chaîne hexadécimale
L'exemple Java suivant convertit un tableau d'octets en chaîne hexadécimale :
private static final char[] DIGITS = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
private static String toHexString(byte[] bytes) {
char[] chars = new char[bytes.length * 2];
int j = 0;
for (byte b : bytes) {
chars[j++] = DIGITS[(b & 0xF0) >> 4];
chars[j++] = DIGITS[b & 0x0F];
}
return new String(chars, 0, j);
}
public void testToHexString() {
String s = "Hello, world";
// getBytes() returns the UTF-8 byte array for the string
byte[] bytes = s.getBytes(Charset.forName("UTF-8"));
String hexString = toHexString(bytes);
System.out.println(hexString); // Output: 48656c6c6f2c20776f726c64
}