日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

動(dòng)態(tài)列

云原生多模數(shù)據(jù)庫 Lindorm寬表引擎支持動(dòng)態(tài)列功能,即創(chuàng)建表時(shí)未顯式指定的列,在實(shí)際業(yè)務(wù)中動(dòng)態(tài)寫入數(shù)據(jù)并執(zhí)行查詢。本文介紹如何通過Lindorm SQL實(shí)現(xiàn)動(dòng)態(tài)列能力的開啟、寫入以及查詢。

背景信息

傳統(tǒng)關(guān)系型數(shù)據(jù)庫表的Schema必須預(yù)先定義,如果要增加列,則需要變更表屬性。變更大表的表屬性是一個(gè)非常耗時(shí)的操作。同時(shí),預(yù)定義的Schema給業(yè)務(wù)的設(shè)計(jì)會(huì)帶來很多不便。但是Lindorm寬表引擎原生支持動(dòng)態(tài)列,列無需提前定義,您可以直接使用Lindorm SQL來對(duì)動(dòng)態(tài)列進(jìn)行讀寫操作。

注意事項(xiàng)

如果您需要使用動(dòng)態(tài)列功能,請(qǐng)注意以下幾點(diǎn):

  • 確保云原生多模數(shù)據(jù)庫 Lindorm寬表引擎為2.2.19及以上版本,具體操作請(qǐng)參見升級(jí)小版本

  • Lindorm寬表中動(dòng)態(tài)列類型均為VARBINARY,查詢動(dòng)態(tài)列和寫入動(dòng)態(tài)列時(shí)都必須將動(dòng)態(tài)列類型轉(zhuǎn)化成字節(jié)數(shù)組。

  • 通過Lindorm SQL管理動(dòng)態(tài)列,查詢動(dòng)態(tài)列和寫入動(dòng)態(tài)列操作支持以云數(shù)據(jù)庫HBase兼容方式創(chuàng)建和寫入的表。

開啟動(dòng)態(tài)列

重要

一張表的動(dòng)態(tài)列功能一旦啟用則無法關(guān)閉。

動(dòng)態(tài)列的開啟可以通過以下兩種方式:

  • 在創(chuàng)建表格時(shí)通過WITH子句開啟動(dòng)態(tài)列功能。

    CREATE TABLE t_dynamic (p1 INT, c1 INT, c2 VARCHAR, PRIMARY KEY(p1)) WITH (DYNAMIC_COLUMNS='true');
  • 通過修改表的屬性開啟動(dòng)態(tài)列功能。

    ALTER TABLE t_dynamic SET 'DYNAMIC_COLUMNS' = 'true';

    結(jié)果驗(yàn)證

    您可以通過以下語句驗(yàn)證表是否已成功開啟動(dòng)態(tài)列功能。

    SHOW TABLE VARIABLES FROM t_dynamic LIKE 'DYNAMIC_COLUMNS';
    說明

    開啟動(dòng)態(tài)列后,您可以修改表的屬性或者在表的Schema中增加新的列,例如執(zhí)行以下語句表示新增c3列,數(shù)據(jù)類型為INT。

    ALTER TABLE t_dynamic ADD COLUMN c3 int;

    如果您在此之前寫入過名為c3的動(dòng)態(tài)列,由于寫入的數(shù)據(jù)類型均為VARBINARY,查詢數(shù)據(jù)和寫入數(shù)據(jù)時(shí)會(huì)拋出異常,如果新增列的數(shù)據(jù)類型為VARBINARY就不會(huì)出現(xiàn)這個(gè)異常。因此,變更動(dòng)態(tài)列表的Schema時(shí)需要注意數(shù)據(jù)類型不同的情況,盡量避免預(yù)定義列和動(dòng)態(tài)列重名。

寫入動(dòng)態(tài)列

SQL文本寫入

寫入動(dòng)態(tài)列表的語法與寫入普通列表的語法一致,開啟動(dòng)態(tài)列之后,可以寫入沒有預(yù)先在Schema中定義的列,但是動(dòng)態(tài)列的類型只能為VARBINARY(即字節(jié)數(shù)組)。Lindorm支持用戶使用Lindorm-cli直接以SQL文本的方式將數(shù)據(jù)寫入動(dòng)態(tài)列,此時(shí)UPSERT語句中指定的動(dòng)態(tài)列的值必須為數(shù)據(jù)的十六進(jìn)制字符串形式(即使用十六進(jìn)制字符(0-9, A-F)來表示二進(jìn)制數(shù)據(jù)的形式。以下簡稱HexString)。

說明

一個(gè)字節(jié)的范圍是0~255,十六進(jìn)制表示為0x00~0xFF。對(duì)于一個(gè)字節(jié)數(shù)組{0x00, 0xFF},它的HexString就是00FF,將字節(jié)數(shù)組轉(zhuǎn)換為HexString的代碼請(qǐng)參見附錄:字節(jié)數(shù)組轉(zhuǎn)換為HexString的實(shí)現(xiàn)示例

寫入動(dòng)態(tài)列的場景示例如下:

  • 執(zhí)行以下語句在t_dynamic表中寫入c3列,c3列為動(dòng)態(tài)列,寫入成功。

    UPSERT INTO t_dynamic (p1, c2, c3) VALUES (1, '1', '41');
  • 執(zhí)行以下語句在t_dynamic表中寫入c4列,c4列為動(dòng)態(tài)列,寫入成功。

    UPSERT INTO t_dynamic (p1, c4) VALUES (2, 'ef0011');
  • 在SQL引擎2.6.8及以上的版本中,為了避免混淆普通字符串和HexString,支持在SQL文本中通過下述形式指定HexString。

    UPSERT INTO t_dynamic(p1, c4) VALUES (3, x'ef0011');

    上述語句保存的動(dòng)態(tài)列c4的數(shù)據(jù)實(shí)際是0xEF0x000x11這三個(gè)字節(jié),而非ef0011這個(gè)字符串(ef0011字符串需要占用6個(gè)字節(jié)的存儲(chǔ)空間)。

    說明

    如何查看Lindorm SQL的版本,請(qǐng)參見SQL版本說明

  • 執(zhí)行以下語句在t_dynamic表中寫入c5列,c5列為動(dòng)態(tài)列。由于動(dòng)態(tài)列c5的值f不是偶數(shù)長度的HexString,所以寫入失敗,需要將f修改為0f

    UPSERT INTO t_dynamic (p1, c5) VALUES (4, 'f');
  • 執(zhí)行以下語句在t_dynamic表中寫入動(dòng)態(tài)列c6,但由于指定的值gf不是HexString,所以該語句執(zhí)行時(shí)報(bào)錯(cuò)。

    UPSERT INTO t_dynamic (p1, c6) VALUES (5, x'gf');

SQL參數(shù)化寫入(推薦)

相較于上述直接通過SQL文本直接寫動(dòng)態(tài)列,更推薦的做法是在應(yīng)用程序中通過SQL綁參的方式綁定要寫入的字節(jié)數(shù)組實(shí)現(xiàn)寫入。如果您需要將字符串或者數(shù)值型的值寫入動(dòng)態(tài)列中,那么需要先將這些值編碼成字節(jié)數(shù)組,然后通過綁參寫入。

以表t_dynamic為例,使用Java代碼綁參寫入動(dòng)態(tài)列的代碼示例如下:

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);

//插入3列,其中p1,c1為Schema預(yù)先定義好的列,c2沒有預(yù)先定義,為動(dòng)態(tài)列寫入。
String sqlUpsert = "upsert into " + tableName + "(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});
    int updated = stmt.executeUpdate();
    Assert.assertEquals(1, updated);
}
重要

使用綁參方式寫入數(shù)據(jù)時(shí),理論上可以通過類似JDBC中的PreparedStatement#setString( )方法傳入一個(gè)HexString來寫入數(shù)據(jù),但強(qiáng)烈建議不要這樣操作,尤其是使用MySQL協(xié)議與Lindorm進(jìn)行交互時(shí)。因?yàn)樵贛ySQL協(xié)議中,客戶端傳入的字符串型參數(shù)會(huì)以字節(jié)數(shù)組的形式傳至服務(wù)端,可能導(dǎo)致數(shù)據(jù)的二義性,因此強(qiáng)烈建議避免這種操作。

查詢動(dòng)態(tài)列

查詢動(dòng)態(tài)列的場景分為以下幾種:

  • 顯式指定查詢字段為動(dòng)態(tài)列。查詢動(dòng)態(tài)列表的語法與查詢普通列表的語法一致,開啟動(dòng)態(tài)列之后,可以查詢沒有預(yù)先在Schema中定義的列,如下示例,c3和c4是創(chuàng)建表后新增的動(dòng)態(tài)列。

    SELECT p1, c2, c3, c4 FROM t_dynamic WHERE p1 = 1;

    返回結(jié)果如下:

    +----+----+------+------+
    | p1 | c2 |  c3  |  c4  |
    +----+----+------+------+
    | 1  | 1  | 0x41 | null |
    +----+----+------+------+
  • 不確定表中已包含哪些動(dòng)態(tài)列時(shí),可以使用SELECT *查詢動(dòng)態(tài)列表。Lindorm SQL為了保證結(jié)果集元數(shù)據(jù)的正確性,強(qiáng)制要求在此類查詢語句后添加LIMIT子句來限定結(jié)果集的大小。

    SELECT * FROM t_dynamic LIMIT 10;

    返回結(jié)果如下:

    +----+------+------+------+----------+
    | p1 |  c1  |  c2  |  c3  |    c4    |
    +----+------+------+------+----------+
    | 1  | null | 1    | 0x41 | null     |
    | 2  | null | null | null | 0xef0011 |
    | 3  | null | null | null | 0xef0011 |
    +----+------+------+------+----------+
    重要

    對(duì)于動(dòng)態(tài)列表的SELECT *查詢操作,LIMIT的默認(rèn)最大值為5000,超過最大值會(huì)報(bào)錯(cuò)。

  • WHERE條件中使用動(dòng)態(tài)列。

    為了確保查詢語句的性能WHERE條件中需包含主鍵或索引列,如果您希望在查詢的過濾條件中使用動(dòng)態(tài)列進(jìn)行過濾,那么使用SQL文本查詢時(shí),動(dòng)態(tài)列的過濾條件必須指定為HexString;使用綁參方式進(jìn)行查詢時(shí),過濾條件建議直接指定為原始的字節(jié)數(shù)組。

    例如表t_dynamicc4為動(dòng)態(tài)列,那么查詢成功的語句如下示例:

    SELECT p1, c4 FROM t_dynamic WHERE p1 = 3 AND c4 = x'ef0011';

    作為對(duì)比,下述查詢示例中由于給動(dòng)態(tài)列c4指定的過濾條件1不是一個(gè)HexString,所以該查詢執(zhí)行失敗。

    SELECT p1, c1, c4 FROM t_dynamic WHERE p1 = 2 AND c4 = '1';

動(dòng)態(tài)列數(shù)據(jù)的顯示

使用不同的命令行工具時(shí),動(dòng)態(tài)列的查詢結(jié)果顯示方式不同,具體如下:

Lindorm-cli

HexString

Lindorm-cli會(huì)以HexString的形式展示動(dòng)態(tài)列的查詢結(jié)果。以表t_dynamic為例,查詢語句如下:

SELECT p1, c3, c4 FROM t_dynamic WHERE p1 = 1;

返回結(jié)果如下:

+----+------+------+------+----------+
| p1 |  c1  |  c2  |  c3  |    c4    |
+----+------+------+------+----------+
| 1  | null | 1    | 0x41 | null     |
| 2  | null | null | null | 0xef0011 |
| 3  | null | null | null | 0xef0011 |
+----+------+------+------+----------+

上述結(jié)果集中動(dòng)態(tài)列c3的第一行查詢結(jié)果0x41表示字母A。

字符串格式

如果您期望查詢結(jié)果以字符串的格式返回,需要通過Lindorm-cli的連接語句末尾添加-bytesOutputAsString參數(shù),示例如下:

./lindorm-cli -url <jdbc url> -username <用戶名> -password <密碼> -bytesOutputAsString
說明

連接參數(shù)說明請(qǐng)參見步驟二:連接Lindorm寬表引擎

執(zhí)行相同查詢語句SELECT p1, c3, c4 FROM t_dynamic WHERE p1 = 1;,將返回如下結(jié)果:

+-----+-------+---------+
| p1  |   c3  |   c4    |
+-----+-------+---------+
|  1  | A     |  null   |
+-----+-------+---------+

MySQL命令行

MySQL命令行并不會(huì)默認(rèn)顯示動(dòng)態(tài)列的數(shù)據(jù),這些二進(jìn)制數(shù)據(jù)將會(huì)以?表示。

附錄:字節(jié)數(shù)組轉(zhuǎn)換為HexString的實(shí)現(xiàn)示例

在Java中,使用下述代碼可以將一個(gè)字節(jié)數(shù)組轉(zhuǎn)換為HexString。

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;
  int j = 0;
  chars = new char[bytes.length * 2];
  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";
  // 對(duì)于字符串類型,可以直接使用String的getBytes方法獲得對(duì)象對(duì)應(yīng)的byte[]
  byte[] bytes = s.getBytes(Charset.forName("UTF-8"));
  String hexString = toHexString(bytes);
  System.out.println(hexString); //打印結(jié)果為: 48656c6c6f2c20776f726c64
}