跳到主要内容

半结构化编码

本文档主要介绍 seekdb 支持的 JSON 数据半结构化编码功能。

seekdb 支持建表时开启半结构化编码,主要由表级别参数 SEMISTRUCT_PROPERTIES 控制,同时也要设置表的 ROW_FORMAT=COMPRESSED,否则会报错。

注意事项

  • SEMISTRUCT_PROPERTIES=(encoding_type=encoding) 时,表被认为是半结构化表,即整张表中的 JSON 列都会启用半结构化编码;
  • SEMISTRUCT_PROPERTIES=(encoding_type=none) 时,表被认为是结构化表。
  • 同时,还支持通过 freq_threshold 参数设置频率阈值。当启用半结构化编码时,系统会分析 JSON 数据中各个路径的出现频率,将出现频率高于设定阈值的路径作为独立的子列存储,这些子列就称为频繁列。例如,假设您有一个用户表,JSON 字段存储用户信息,如果 90% 的用户都有 nameage 字段,那么系统会自动将 nameage 提取为独立的频繁列,查询时直接访问这些列而不需要解析整个 JSON,从而提升查询性能。
  • 当前 encoding_typefreq_threshold 是 Online DDL 语法,不支持 Offline DDL 语法。

数据形式

把 JSON 数据按照一定的形式拆分成结构化列的方式存储,那么从 JSON 列拆分出的列被称为子列。子列可以被拆分为不同的类型,包括稀疏列和频繁列。

  • 稀疏列:部分 JSON 有,部分 JSON 没有的子列,出现频率低于表级别参数 freq_threshold 指定的阈值。
  • 频繁列:JSON 中出现频率高于表级别参数 freq_threshold 指定的阈值的子列,这些子列会被作为独立的列存储,以提升过滤查询性能。

例如:

{"id": 1001, "name": "n1", "nickname": "nn1"}
{"id": 1002, "name": "n2", "nickname": "nn2"}
{"id": 1003, "name": "n3", "nickname": "nn3"}
{"id": 1004, "name": "n4", "nickname": "nn4"}
{"id": 1005, "name": "n5"}

其中 idname 是每个 JSON 都有的字段,出现频率为 100%,nickname 只有 4 个 JSON 有,出现频率为 80%。

如果 freq_threshold 定义为 100%,那么 nickname 就会被推导为稀疏列,idname 就会被推导为频繁列;如果定义为 80%,那么 nicknameidname 就都会被推导为频繁列。

示例

  1. 启用半结构化编码

    提示

    如果启用半结构化编码功能,请务必保证配置项 micro_block_merge_verify_level 为默认配置 2 ,切勿关闭微块合并校验。

    tab 建表时启用的示例

    CREATE TABLE t1(  j json) 
    ROW_FORMAT=COMPRESSED
    SEMISTRUCT_PROPERTIES=(encoding_type=encoding, freq_threshold=50);

    更多语法说明请见 CREATE TABLE

    tab 修改已有表来启用半结构化编码的示例

    CREATE TABLE t1(j json);
    ALTER TABLE t1 SET ROW_FORMAT=COMPRESSED SEMISTRUCT_PROPERTIES = (encoding_type=encoding, freq_threshold=50);

    更多语法说明请见 ALTER TABLE

    一些修改限制:

    • 修改频繁列阈值,如果没开启半结构化不报错,但是不生效。
    • 在旁路导入或表被锁定时,freq_threshold 参数无法修改。
    • 修改其中一个子配置项,不影响其余的子配置项。
  2. 关闭半结构化编码

    SEMISTRUCT_PROPERTIES 设置为 (encoding_type=none) 时,将关闭半结构化编码。此操作不会影响已有的数据,仅对后续写入的数据生效。以下是关闭半结构化编码的示例:

    ALTER TABLE t1 SET ROW_FORMAT=COMPRESSED SEMISTRUCT_PROPERTIES = (encoding_type=none);
  3. 查询半结构编码配置

    通过 SHOW CREATE TABLE 语句查询半结构化编码配置。示例语句如下:

    SHOW CREATE TABLE t1;

    返回结果如下:

    +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table |
    +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | t1 | CREATE TABLE `t1` (
    `j` json DEFAULT NULL
    ) ORGANIZATION INDEX DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPRESSED COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE ENABLE_MACRO_BLOCK_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 SEMISTRUCT_PROPERTIES=(ENCODING_TYPE=ENCODING, FREQ_THRESHOLD=50) |
    +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set

    SEMISTRUCT_PROPERTIES=(encoding_type=encoding) 时,查询才会显示该配置项信息,表示开启了半结构化编码功能。

    使用半结构化编码可以提高 JSON_VALUE() 函数 条件过滤查询的性能。基于 JSON 半结构化编码技术,seekdb 对 JSON_VALUE 表达式条件过滤查询场景进行了性能优化。由于 JSON 数据已被拆分为子列,系统可以直接基于编码后的子列数据进行过滤,无需还原完整的 JSON 结构,从而显著提升查询效率。

    查询示例如下:

    -- 查询 name 字段值为 'Devin' 的行
    SELECT * FROM t WHERE JSON_VALUE(j_doc, '$.name' RETURNING CHAR) = 'Devin';

    字符集注意事项如下:

    • seekdb 的 JSON 使用 utf8_bin 编码。

    • 为确保字符串白盒过滤正常工作,建议设置:

    SET @@collation_server = 'utf8mb4_bin';
    SET @@collation_connection='utf8mb4_bin';