eldenmoon commented on code in PR #2753:
URL: https://github.com/apache/doris-website/pull/2753#discussion_r2278409038
##########
i18n/zh-CN/docusaurus-plugin-content-docs/current/sql-manual/basic-element/sql-data-types/semi-structured/VARIANT.md:
##########
@@ -9,352 +9,401 @@
## 描述
-在 Doris 2.1 中引入一种新的数据类型 VARIANT,它可以存储半结构化 JSON
数据。它允许存储包含不同数据类型(如整数、字符串、布尔值等)的复杂数据结构,而无需在表结构中提前定义具体的列。VARIANT
类型特别适用于处理复杂的嵌套结构,而这些结构可能随时会发生变化。在写入过程中,该类型可以自动根据列的结构、类型推断列信息,动态合并写入的
schema,并通过将 JSON 键及其对应的值存储为列和动态子列。
+VARIANT 类型用于存储半结构化 JSON 数据,可包含不同基础类型(整数、字符串、布尔等)以及一层数组与嵌套对象。写入时会自动基于 JSON Path
推断子列结构与类型,并将高频路径物化为独立子列,充分利用列式存储和向量化执行,兼顾灵活性与性能。
-### Note
+## 使用 VARIANT 类型
-相比 JSON 类型有以下优势:
+### 建表语法
-1. 存储方式不同,JSON 类型是以二进制 JSONB 格式进行存储,整行 JSON 以行存的形式存储到 segment 文件中。而 VARIANT
类型在写入的时候进行类型推断,将写入的 JSON 列存化。比 JSON 类型有更高的压缩比,存储空间更小。
-2. 查询方式不同,查询不需要进行解析。VARIANT 充分利用 Doris 中列式存储、向量化引擎、优化器等组件给用户带来极高的查询性能。
-下面是基于 clickbench 数据测试的结果:
+建表时将列类型声明为 VARIANT:
-| | 存储空间 |
-|--------------|------------|
-| 预定义静态列 | 12.618 GB |
-| VARIANT 类型 | 12.718 GB |
-| JSON 类型 | 35.711 GB |
+```sql
+CREATE TABLE IF NOT EXISTS ${table_name} (
+ k BIGINT,
+ v VARIANT
+)
+PROPERTIES("replication_num" = "1");
+```
-**节省约 65% 存储容量**
+通过 Schema Template 约束部分 Path 的类型(更多见“扩展类型”):
-| 查询次数 | 预定义静态列 | VARIANT 类型 | JSON 类型 |
-|----------------|--------------|--------------|-----------------|
-| 第一次查询 (cold) | 233.79s | 248.66s | **大部分查询超时** |
-| 第二次查询 (hot) | 86.02s | 94.82s | 789.24s |
-| 第三次查询 (hot) | 83.03s | 92.29s | 743.69s |
+```sql
+CREATE TABLE IF NOT EXISTS ${table_name} (
+ k BIGINT,
+ v VARIANT <
+ 'id' : INT, -- path 为 id 的子列被限制为 INT 类型
+ 'message*' : STRING, -- 前缀匹配 message* 的子列被限制为 STRING 类型
+ 'tags*' : ARRAY<TEXT> -- 前缀匹配 tags* 的子列被限制为 ARRAY<TEXT> 类型
+ >
+)
+PROPERTIES("replication_num" = "1");
+```
-[测试集](https://github.com/ClickHouse/ClickBench/blob/main/doris/queries.sql) 一共
43 个查询语句
+### 查询语法
-**查询提速 8+ 倍,查询性能与静态列相当**
+```sql
+-- 访问嵌套字段(返回类型为 VARIANT,需要显式或隐式 CAST 才能聚合/比较)
+SELECT v['properties']['title'] FROM ${table_name};
-## 举例
+-- 聚合前显式 CAST 为确定类型
+SELECT CAST(v['properties']['title'] AS STRING) AS title
+FROM ${table_name}
+GROUP BY title;
-用一个从建表、导数据、查询全周期的例子说明 VARIANT 的功能和用法。
+-- 数组查询示例
+SELECT *
+FROM ${table_name}
+WHERE ARRAY_CONTAINS(CAST(v['tags'] AS ARRAY<TEXT>), 'Doris');
+```
-**建表语法**
+## 基本类型
+
+VARIANT 自动推断的子列基础类型包括:
+
+<table>
+<tr><td>支持的类型<br/></td></tr>
+<tr><td>TinyInt<br/></td></tr>
+<tr><td>NULL(等价于 JSON 的 null)<br/></td></tr>
+<tr><td>BigInt(64 bit)<br/>Double<br/></td></tr>
+<tr><td>String(Text)<br/></td></tr>
+<tr><td>Jsonb<br/></td></tr>
+<tr><td>Variant(嵌套对象)<br/></td></tr>
+<tr><td>Array<T>(仅支持一维)<br/></td></tr>
+</table>
+
+简单的 INSERT 示例:
+
+```sql
+INSERT INTO vartab VALUES
+ (1, 'null'),
+ (2, NULL),
+ (3, 'true'),
+ (4, '-17'),
+ (5, '123.12'),
+ (6, '1.912'),
+ (7, '"A quote"'),
+ (8, '[-1, 12, false]'),
+ (9, '{ "x": "abc", "y": false, "z": 10 }'),
+ (10, '"2021-01-01"');
+```
-建表语法关键字 VARIANT
+提示:日期/时间戳等非标准 JSON 类型在未指定 Schema 时会以字符串形式存储;如需较高计算效率,建议将其提取为静态列或在 Schema
Template 中明确声明类型。
-``` sql
--- 无索引
-CREATE TABLE IF NOT EXISTS ${table_name} (
- k BIGINT,
- v VARIANT
-)
-table_properties;
+## 扩展类型(Schema Template)
--- 在v列创建索引,可选指定分词方式,默认不分词
-CREATE TABLE IF NOT EXISTS ${table_name} (
- k BIGINT,
- v VARIANT,
- INDEX idx_var(v) USING INVERTED [PROPERTIES("parser" =
"english|unicode|chinese")] [COMMENT 'your comment']
-)
-table_properties;
+除基本类型外,VARIANT 还可通过 Schema Template 声明以下扩展类型:
--- 在v列创建bloom filter
-CREATE TABLE IF NOT EXISTS ${table_name} (
- k BIGINT,
- v VARIANT
+- Number(扩展)
+ - Decimal:Decimal32 / Decimal64 / Decimal128 / Decimal256
+ - LargeInt
+- Datetime
+- Date
+- IPV4 / IPV6
+- Boolean
+- ARRAY<T>(T 为以上任意类型,仅支持一维)
+
+注意:预定义的 Schema 只能在建表时指定,当前不支持通过 ALTER 修改(后续可能支持“新增”子列定义,但不支持修改既有子列类型)。
+
+示例:
+
+```sql
+CREATE TABLE test_var_schema (
+ id BIGINT NOT NULL,
+ v1 VARIANT<
+ 'large_int_val': LARGEINT,
+ 'string_val': STRING,
+ 'decimal_val': DECIMAL(38, 9),
+ 'datetime_val': DATETIME,
+ 'ip_val': IPV4
+ > NULL
)
-...
-properties("replication_num" = "1", "bloom_filter_columns" = "v");
+PROPERTIES ("replication_num" = "1");
+
+INSERT INTO test_var_schema VALUES (1, '{
+ "large_int_val" : "123222222222222222222222",
+ "string_val" : "Hello World",
+ "decimal_val" : 1.11111111,
+ "datetime_val" : "2025-05-16 11:11:11",
+ "ip_val" : "127.0.0.1"
+}');
+
+SELECT variant_type(v1) FROM test_var_schema;
+
++----------------------------------------------------------------------------------------------------------------------------+
+| variant_type(v1)
|
++----------------------------------------------------------------------------------------------------------------------------+
+|
{"datetime_val":"datetimev2","decimal_val":"decimal128i","ip_val":"ipv4","large_int_val":"largeint","string_val":"string"}
|
++----------------------------------------------------------------------------------------------------------------------------+
```
-**查询语法**
+`{"date": 2020-01-01}` 与 `{"ip": 127.0.0.1}` 均为非法 JSON 文本,正确格式应为 `{"date":
"2020-01-01"}` 与 `{"ip": "127.0.0.1"}`。
-``` sql
--- 使用 v['a']['b'] 形式如下,v['properties']['title']类型是VARIANT
-SELECT v['properties']['title'] from ${table_name}
-```
+一旦指定 Schema,若 JSON 实际类型与 Schema 冲突且无法转换,将保存为 NULL。例如:
-### 基于 github events 数据集示例
+```sql
+INSERT INTO test_var_schema VALUES (1, '{
+ "decimal_val" : "1.11111111",
+ "ip_val" : "127.xxxxxx.xxxx",
+ "large_int_val" : "aaabbccc"
+}');
-这里用 github events 数据展示 VARIANT 的建表、导入、查询。
-下面是格式化后的一行数据
+-- 仅 decimal_val 保留
+SELECT * FROM test_var_schema;
-``` json
-{
- "id": "14186154924",
- "type": "PushEvent",
- "actor": {
- "id": 282080,
- "login": "brianchandotcom",
- "display_login": "brianchandotcom",
- "gravatar_id": "",
- "url": "https://api.github.com/users/brianchandotcom",
- "avatar_url": "https://avatars.githubusercontent.com/u/282080?"
- },
- "repo": {
- "id": 1920851,
- "name": "brianchandotcom/liferay-portal",
- "url": "https://api.github.com/repos/brianchandotcom/liferay-portal"
- },
- "payload": {
- "push_id": 6027092734,
- "size": 4,
- "distinct_size": 4,
- "ref": "refs/heads/master",
- "head": "91edd3c8c98c214155191feb852831ec535580ba",
- "before": "abb58cc0db673a0bd5190000d2ff9c53bb51d04d",
- "commits": [""]
- },
- "public": true,
- "created_at": "2020-11-13T18:00:00Z"
-}
++------+-----------------------------+
+| id | v1 |
++------+-----------------------------+
+| 1 | {"decimal_val":1.111111110} |
++------+-----------------------------+
```
-**建表**
+Schema 仅指导“存储层”的持久化类型,计算逻辑仍以实际数据的动态类型为准:
+
+```sql
+-- 实际 v['a'] 的运行时类型仍可能是 STRING
+SELECT variant_type(CAST('{"a" : "12345"}' AS VARIANT<'a' : INT>)['a']);
+```
-- 创建了三个 VARIANT 类型的列, `actor`,`repo` 和 `payload`
-- 创建表的同时创建了 `payload` 列的倒排索引 `idx_payload`
-- USING INVERTED 指定索引类型是倒排索引,用于加速子列的条件过滤
-- `PROPERTIES("parser" = "english")` 指定采用 english 分词
+通配符与匹配顺序:
-``` sql
-CREATE DATABASE test_variant;
-USE test_variant;
-CREATE TABLE IF NOT EXISTS github_events (
+```sql
+CREATE TABLE test_var_schema (
id BIGINT NOT NULL,
- type VARCHAR(30) NULL,
- actor VARIANT NULL,
- repo VARIANT NULL,
- payload VARIANT NULL,
- public BOOLEAN NULL,
- created_at DATETIME NULL,
- INDEX idx_payload (`payload`) USING INVERTED PROPERTIES("parser" =
"english") COMMENT 'inverted index for payload'
+ v1 VARIANT<
+ 'enumString*' : STRING,
+ 'enum*' : ARRAY<TEXT>,
+ 'ip*' : IPV6
+ > NULL
)
-DUPLICATE KEY(`id`)
-DISTRIBUTED BY HASH(id) BUCKETS 10
-properties("replication_num" = "1");
+PROPERTIES ("replication_num" = "1");
+
+-- 若 enumString1 同时匹配上述两个 pattern,则采用定义顺序中第一个匹配到的类型(STRING)
```
-**需要注意的是:**
+如列名中包含 `*` 且希望按名称精确匹配,可使用:
-:::tip
+```sql
+v1 VARIANT<
+ MATCH_NAME 'enumString*' : STRING
Review Comment:
上面就是介绍通配符匹配
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]