Bancos de dados relacionais tradicionais exigem a pré-definição de todas as colunas antes da gravação de dados. Adicionar uma coluna a uma tabela grande é uma alteração de esquema demorada que pode bloquear suas operações de negócio. O recurso de colunas dinâmicas do LindormTable permite gravar dados em colunas não definidas no esquema da tabela, sem necessidade de modificação de esquema ou tempo de inatividade.
Pré-requisitos
Antes de começar, certifique-se de que:
Sua instância do LindormTable esteja na versão 2.2.19 ou posterior. Para atualizar, consulte Atualizar a versão secundária do mecanismo de uma instância do Lindorm
Você compreende que as colunas dinâmicas não podem ser desativadas após serem ativadas para uma tabela
Como funciona
Todos os dados armazenados em colunas dinâmicas são do tipo VARBINARY, que representa arrays de bytes. Ao gravar ou consultar colunas dinâmicas via Lindorm-cli ou SQL, codifique os valores como strings hexadecimais — dados binários representados por caracteres hexadecimais (0–9 e A–F).
A mesma tabela pode conter linhas com diferentes conjuntos de colunas dinâmicas. Por exemplo, a tabela a seguir mostra três linhas em que cada uma possui um conjunto distinto de colunas dinâmicas:
+----+------+----------+
| p1 | c3 | c4 |
+----+------+----------+
| 1 | 0x41 | null |
| 2 | null | 0xef0011 |
| 3 | null | 0xef0011 |
+----+------+----------+
Se você utilizar a API HBase para Java para criar uma tabela ou gravar dados, também poderá usar o Lindorm SQL para ler e gravar colunas dinâmicas nessa tabela.
Ativar colunas dinâmicas
As colunas dinâmicas não podem ser desativadas depois de ativadas para uma tabela.
Ative as colunas dinâmicas usando um dos métodos a seguir:
-
Na criação da tabela, utilizando a cláusula
WITH:CREATE TABLE t_dynamic (p1 INT, c1 INT, c2 VARCHAR, PRIMARY KEY(p1)) WITH (DYNAMIC_COLUMNS='true'); -
Em uma tabela existente, modificando suas propriedades:
ALTER TABLE t_dynamic SET 'DYNAMIC_COLUMNS' = 'true';
Verificar se as colunas dinâmicas estão ativadas
SHOW TABLE VARIABLES FROM t_dynamic LIKE 'DYNAMIC_COLUMNS';
Adicionar colunas predefinidas após ativar colunas dinâmicas
Mesmo após ativar as colunas dinâmicas, você ainda pode adicionar novas colunas predefinidas ao esquema:
ALTER TABLE t_dynamic ADD COLUMN c3 int;
Se você já tiver gravado dados em uma coluna dinâmica chamada c3 (armazenada como VARBINARY) e posteriormente adicionar c3 como uma coluna INT, as consultas e inserções em c3 como INT falharão devido ao conflito de tipos. Esse erro não ocorre se você adicionar c3 com o tipo VARBINARY. Não reutilize o nome de uma coluna dinâmica existente ao adicionar colunas predefinidas.
Gravar dados em colunas dinâmicas
Gravar usando parâmetros SQL (recomendado)
Utilize PreparedStatement com setBytes() para gravar arrays de bytes diretamente. Isso evita a ambiguidade que pode ocorrer ao passar strings hexadecimais como strings simples, especialmente ao usar MySQL para interagir com o Lindorm.
O exemplo a seguir em Java (JDBC) cria uma tabela com colunas dinâmicas ativadas e insere uma linha onde c2 é uma coluna dinâmica:
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();
}
Não passe strings hexadecimais via setString() para colunas dinâmicas, principalmente ao conectar-se através do MySQL. O MySQL envia parâmetros STRING como arrays de bytes, o que pode causar ambiguidade nos dados.
Gravar usando instruções SQL (Lindorm-cli)
Passe os valores como strings hexadecimais nas instruções UPSERT. Cada string hexadecimal representa um array de bytes, onde cada dois dígitos hexadecimais codificam um byte.
Um byte pode ser representado como um número decimal de 0 a 255 ou como dois dígitos hexadecimais de 0x00 a 0xFF. Para converter um array de bytes em uma string hexadecimal, consulte Converter um array de bytes em uma string hexadecimal.
Os exemplos a seguir utilizam a tabela t_dynamic (esquema: chave primária p1 INT, c1 INT, c2 VARCHAR). As colunas c3, c4, c5 e c6 são colunas dinâmicas.
Gravação bem-sucedida — string hexadecimal como string simples:
UPSERT INTO t_dynamic (p1, c2, c3) VALUES (1, '1', '41');
Gravação bem-sucedida — string hexadecimal com múltiplos bytes:
UPSERT INTO t_dynamic (p1, c4) VALUES (2, 'ef0011');
Sintaxe preferencial no Lindorm SQL 2.6.8 e posterior — use o prefixo x'...' para distinguir strings hexadecimais de strings comuns:
UPSERT INTO t_dynamic (p1, c4) VALUES (3, x'ef0011');
O literal x'ef0011' grava três bytes — 0xEF, 0x00 e 0x11 — e não a string de seis caracteres ef0011.
Para verificar sua versão do Lindorm SQL, consulte Versões do SQL.
Falha na gravação — string hexadecimal com comprimento ímpar:
UPSERT INTO t_dynamic (p1, c5) VALUES (4, 'f');
Essa operação falha porque f é um único caractere hexadecimal. Strings hexadecimais devem ter um número par de caracteres (cada byte requer dois dígitos hexadecimais). Use 0f em vez disso.
Falha na gravação — caracteres hexadecimais inválidos:
UPSERT INTO t_dynamic (p1, c6) VALUES (5, x'gf');
Essa operação falha porque g não é um caractere hexadecimal válido (válidos: 0–9, A–F).
Consultar dados em colunas dinâmicas
A sintaxe de consulta é a mesma usada para tabelas regulares. Os exemplos a seguir consultam a tabela t_dynamic após as operações UPSERT acima.
Consultar colunas dinâmicas específicas
Especifique explicitamente os nomes das colunas dinâmicas na cláusula SELECT:
SELECT p1, c2, c3, c4 FROM t_dynamic WHERE p1 = 1;
Resultado:
+----+----+------+------+
| p1 | c2 | c3 | c4 |
+----+----+------+------+
| 1 | 1 | 0x41 | null |
+----+----+------+------+
Descobrir todas as colunas dinâmicas em uma tabela
Use SELECT * com uma cláusula LIMIT para recuperar todas as colunas, incluindo as dinâmicas. A cláusula LIMIT é obrigatória para garantir a integridade dos metadados do conjunto de resultados. O valor máximo padrão de LIMIT é 5.000. Você pode especificar um valor máximo personalizado. Se o valor consultado exceder esse limite, um erro será retornado.
SELECT * FROM t_dynamic LIMIT 10;
Resultado:
+----+------+------+------+----------+
| p1 | c1 | c2 | c3 | c4 |
+----+------+------+------+----------+
| 1 | null | 1 | 0x41 | null |
| 2 | null | null | null | 0xef0011 |
| 3 | null | null | null | 0xef0011 |
+----+------+------+------+----------+
Usar colunas dinâmicas em cláusulas WHERE
Sempre inclua a chave primária ou uma chave de índice na cláusula WHERE para garantir o desempenho da consulta. Ao filtrar por valores de colunas dinâmicas via Lindorm-cli ou SQL, utilize strings hexadecimais.
Consulta bem-sucedida:
SELECT p1, c4 FROM t_dynamic WHERE p1 = 3 AND c4 = x'ef0011';
Falha na consulta — o valor '1' não é uma string hexadecimal:
SELECT p1, c1, c4 FROM t_dynamic WHERE p1 = 2 AND c4 = '1';
Exibir dados em colunas dinâmicas
Os resultados das consultas para colunas dinâmicas são exibidos de forma diferente dependendo da ferramenta cliente utilizada.
Ferramenta de linha de comando do MySQL
A ferramenta de linha de comando do MySQL exibe os valores das colunas dinâmicas como pontos de interrogação (?) por padrão.
Converter um array de bytes em uma string hexadecimal
O exemplo a seguir em Java converte um array de bytes em uma string hexadecimal:
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
}