动态表

SinceVersion 2.0.0

动态schema表是一种特殊的表,其schema随着导入自动进行扩展。目前该功能,主要用于半结构数据,例如JSON等的导入、自动列生成。因为JSON是类型自描述的,所以我们可以从原始文档中提取schema信息,推断最终类型信息。这种特殊的表可以减少人工schema change的操作,并轻松导入半结构数据并自动扩展其schema。

名词解释

  • schema change, 改变表的结构, 例如增加列、减少列, 修改列类型
  • 静态列, 在建表时指定的列, 例如分区列、主键列
  • 动态列, 随着导入自动识别并增加的列

建表

  1. CREATE DATABASE test_dynamic_table;
  2. -- 建表, 并指定静态列类型, 导入遇到对应列会自动转换成静态列的类型
  3. -- 选择随机分桶方式
  4. CREATE TABLE IF NOT EXISTS test_dynamic_table (
  5. qid bigint,
  6. `answers.date` array<datetime>,
  7. `title` string,
  8. ... -- ...标识该表是动态表, 是动态表的语法
  9. )
  10. DUPLICATE KEY(`qid`)
  11. DISTRIBUTED BY RANDOM BUCKETS 5
  12. properties("replication_num" = "1");
  13. -- 可以看到三列Column在表中默认添加, 类型是指定类型
  14. mysql> DESC test_dynamic_table;
  15. +--------------+-----------------+------+-------+---------+-------+
  16. | Field | Type | Null | Key | Default | Extra |
  17. +--------------+-----------------+------+-------+---------+-------+
  18. | qid | BIGINT | Yes | true | NULL | |
  19. | answers.date | ARRAY<DATETIME> | Yes | false | NULL | NONE |
  20. | user | TEXT | Yes | false | NULL | NONE |
  21. +--------------+-----------------+------+-------+---------+-------+
  22. 3 rows in set (0.00 sec)

导入数据

  1. -- example1.json
  2. '{
  3. "title": "Display Progress Bar at the Time of Processing",
  4. "qid": "1000000",
  5. "answers": [
  6. {"date": "2009-06-16T09:55:57.320", "user": "Micha\u0142 Niklas (22595)"},
  7. {"date": "2009-06-17T12:34:22.643", "user": "Jack Njiri (77153)"}
  8. ],
  9. "tag": ["vb6", "progress-bar"],
  10. "user": "Jash",
  11. "creationdate": "2009-06-16T07:28:42.770"
  12. }'
  13. curl -X PUT -T example1.json --location-trusted -u root: -H "read_json_by_line:false" -H "format:json" http://127.0.0.1:8147/api/regression_test_dynamic_table/test_dynamic_table/_stream_load
  14. -- 新增 titleanswers.user tag title creationdate 五列
  15. -- qidanswers.dateuser三列类型与建表时保持一致
  16. -- 新增数组类型默认Default值为空数组[]
  17. mysql> DESC test_dynamic_table;
  18. +--------------+-----------------+------+-------+---------+-------+
  19. | Field | Type | Null | Key | Default | Extra |
  20. +--------------+-----------------+------+-------+---------+-------+
  21. | qid | BIGINT | Yes | true | NULL | |
  22. | answers.date | ARRAY<DATETIME> | Yes | false | NULL | NONE |
  23. | title | TEXT | Yes | false | NULL | NONE |
  24. | answers.user | ARRAY<TEXT> | No | false | [] | NONE |
  25. | tag | ARRAY<TEXT> | No | false | [] | NONE |
  26. | user | TEXT | Yes | false | NULL | NONE |
  27. | creationdate | TEXT | Yes | false | NULL | NONE |
  28. | date | TEXT | Yes | false | NULL | NONE |
  29. +--------------+-----------------+------+-------+---------+-------+
  30. -- 批量导入数据
  31. -- 指定 -H "read_json_by_line:true" 逐行解析JSON
  32. curl -X PUT -T example_batch.json --location-trusted -u root: -H "read_json_by_line:true" -H "format:json" http://127.0.0.1:8147/api/regression_test_dynamic_table/test_dynamic_table/_stream_load
  33. -- 指定 -H "strip_outer_array:true" 整个文件当做一个JSON array解析, array中的每个元素是一行, 解析效率更高效
  34. curl -X PUT -T example_batch_array.json --location-trusted -u root: -H "strip_outer_array:true" -H "format:json" http://127.0.0.1:8147/api/regression_test_dynamic_table/test_dynamic_table/_stream_load

对于dynamic table, 你也可以使用S3load或者Routine load, 使用方式类似

对动态列增加索引

  1. -- 将在titile列上新建倒排索引, 并按照english分词
  2. CREATE INDEX title_idx ON test_dynamic_table (`title`) using inverted PROPERTIES("parser"="english")

类型冲突

在第一批导入会自动推断出统一的类型, 并以此作为最终的Column类型,所以建议保持Column类型的一致, 例如

  1. {"id" : 123}
  2. {"id" : "123"}
  3. -- 类型会被最终推断为Text类型, 如果在后续导入{"id" : 123}则类型会被自动转成String类型
  4. 对于无法统一的类型, 例如
  5. {"id" : [123]}
  6. {"id" : 123}
  7. -- 导入将会报错