Traditional relational databases require you to predefine every column before writing data. Adding a column to a large table is a time-consuming schema change that can block your business. LindormTable's dynamic column feature lets you write data to columns that are not defined in the table schema — without any schema modification or downtime.
Prerequisites
Before you begin, make sure that:
Your LindormTable instance is version 2.2.19 or later. To upgrade, see Upgrade the minor engine version of a Lindorm instance
You understand that dynamic columns cannot be disabled after they are enabled for a table
How it works
All data stored in dynamic columns is of the VARBINARY type, which represents byte arrays. When writing or querying dynamic columns via Lindorm-cli or SQL, values must be encoded as hex strings — binary data represented by hexadecimal characters (0–9 and A–F).
The same table can hold rows with different sets of dynamic columns. For example, the following table shows three rows where each row has a distinct set of dynamic columns:
+----+------+----------+
| p1 | c3 | c4 |
+----+------+----------+
| 1 | 0x41 | null |
| 2 | null | 0xef0011 |
| 3 | null | 0xef0011 |
+----+------+----------+If you use the HBase API for Java to create a table or write data, you can also use Lindorm SQL to read and write dynamic columns in that table.
Enable dynamic columns
Dynamic columns cannot be disabled after they are enabled for a table.
Enable dynamic columns using one of the following methods:
At table creation, using the
WITHclause:CREATE TABLE t_dynamic (p1 INT, c1 INT, c2 VARCHAR, PRIMARY KEY(p1)) WITH (DYNAMIC_COLUMNS='true');On an existing table, by modifying its properties:
ALTER TABLE t_dynamic SET 'DYNAMIC_COLUMNS' = 'true';
Verify dynamic columns are enabled
SHOW TABLE VARIABLES FROM t_dynamic LIKE 'DYNAMIC_COLUMNS';Add predefined columns after enabling dynamic columns
After enabling dynamic columns, you can still add new predefined columns to the schema:
ALTER TABLE t_dynamic ADD COLUMN c3 int;If you previously wrote data to a dynamic column named c3 (stored as VARBINARY), then add c3 as an INT column, queries and inserts on c3 as INT will fail due to the type conflict. This error does not occur if you add c3 with the VARBINARY type. Do not reuse the name of an existing dynamic column when adding predefined columns.
Write data to dynamic columns
Write using SQL parameters (recommended)
Use PreparedStatement with setBytes() to write byte arrays directly. This avoids the ambiguity that can occur when passing hex strings as plain strings — especially when using MySQL to interact with Lindorm.
The following Java (JDBC) example creates a table with dynamic columns enabled and inserts a row where c2 is a dynamic column:
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();
}Do not pass hex strings via setString() for dynamic columns — particularly when connecting through MySQL. MySQL sends STRING parameters as byte arrays, which can cause data ambiguity.
Write using SQL statements (Lindorm-cli)
Pass values as hex strings in UPSERT statements. Each hex string represents a byte array, where every two hexadecimal digits encode one byte.
A byte can be represented as a decimal number from 0 to 255, or as two hexadecimal digits from 0x00 to 0xFF. To convert a byte array to a hex string, see Convert a byte array to a hex string.
The following examples use the t_dynamic table (schema: p1 INT primary key, c1 INT, c2 VARCHAR). Columns c3, c4, c5, and c6 are dynamic columns.
Successful write — hex string as a plain string:
UPSERT INTO t_dynamic (p1, c2, c3) VALUES (1, '1', '41');Successful write — hex string with multiple bytes:
UPSERT INTO t_dynamic (p1, c4) VALUES (2, 'ef0011');Preferred syntax in Lindorm SQL 2.6.8 and later — use `x'...'` prefix to distinguish hex strings from ordinary strings:
UPSERT INTO t_dynamic (p1, c4) VALUES (3, x'ef0011');The x'ef0011' literal writes three bytes — 0xEF, 0x00, and 0x11 — not the six-character string ef0011.
To check your Lindorm SQL version, see SQL versions.
Failed write — odd-length hex string:
UPSERT INTO t_dynamic (p1, c5) VALUES (4, 'f');This fails because f is a single hex character. Hex strings must have an even number of characters (each byte requires two hex digits). Use 0f instead.
Failed write — invalid hex characters:
UPSERT INTO t_dynamic (p1, c6) VALUES (5, x'gf');This fails because g is not a valid hexadecimal character (valid: 0–9, A–F).
Query data in dynamic columns
The query syntax is the same as for regular tables. The following examples query from the t_dynamic table after the UPSERT operations above.
Query specific dynamic columns
Specify dynamic column names explicitly in the SELECT clause:
SELECT p1, c2, c3, c4 FROM t_dynamic WHERE p1 = 1;Result:
+----+----+------+------+
| p1 | c2 | c3 | c4 |
+----+----+------+------+
| 1 | 1 | 0x41 | null |
+----+----+------+------+Discover all dynamic columns in a table
Use SELECT * with a LIMIT clause to retrieve all columns, including dynamic ones. The LIMIT clause is required to ensure the integrity of the metadata of the result set. The default maximum value of LIMIT is 5,000. You can specify a maximum value. If the queried value exceeds the maximum value, an error is returned.
SELECT * FROM t_dynamic LIMIT 10;Result:
+----+------+------+------+----------+
| p1 | c1 | c2 | c3 | c4 |
+----+------+------+------+----------+
| 1 | null | 1 | 0x41 | null |
| 2 | null | null | null | 0xef0011 |
| 3 | null | null | null | 0xef0011 |
+----+------+------+------+----------+Use dynamic columns in WHERE clauses
Always include the primary key or an index key in the WHERE clause to ensure query performance. When filtering on dynamic column values via Lindorm-cli or SQL, use hex strings.
Successful query:
SELECT p1, c4 FROM t_dynamic WHERE p1 = 3 AND c4 = x'ef0011';Failed query — the value '1' is not a hex string:
SELECT p1, c1, c4 FROM t_dynamic WHERE p1 = 2 AND c4 = '1';Display data in dynamic columns
Query results for dynamic columns are displayed differently depending on the client tool.
MySQL command-line tool
The MySQL command-line tool displays dynamic column values as question marks (?) by default.
Convert a byte array to a hex string
The following Java example converts a byte array to a hex string:
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
}