下载
编译与部署
开始使用
操作手册
- 数据导入
- 表结构变更
- 物化视图
- HTTP API
- FE
- MANAGER
- Bootstrap Action
- Cancel Load Action
- Check Decommission Action
- Check Storage Type Action
- Config Action
- Connection Action
- Get DDL Statement Action
- Get Load Info Action
- Get Load State
- Get FE log file
- Get Small File
- HA Action
- Hardware Info Action
- Health Action
- Log Action
- Logout Action
- Meta Action
- Meta Action
- Meta Replay State Action
- Profile Action
- Query Detail Action
- Query Profile Action
- Row Count Action
- Session Action
- Set Config Action
- Show Data Action
- Show Meta Info Action
- Show Proc Action
- Show Runtime Info Action
- Statement Execution Action
- System Action
- Table Query Plan Action
- Table Row Count Action
- Table Schema Action
- Upload Action
- CANCEL LABEL
- Compaction Action
- CONNECTION
- getlogfile
- GET LABEL STATE
- GET TABLETS ON A PARTICULAR BE
- PROFILE
- QUERY DETAIL
- RESTORE TABLET
- SHOW DATA
- MIGRATE SINGLE TABLET TO A PARTICULAR DISK
- GET TABLETS DISTRIBUTION BETWEEN DIFFERENT DISKS
- FE
- 运维操作
- 配置文件
- 拦截规则
- 备份与恢复
- Broker
- Colocation Join
- Bucket Shuffle Join
- 动态分区
- 数据导出
- 导出查询结果集
- 分区缓存
- 权限管理
- LDAP
- 资源管理
- 查询执行的统计
- Runtime Filter
- Segment V2 升级手册
- 文件管理器
- SQL MODE
- 时区
- 变量
- 更新
- 多租户和资源划分
最佳实践
扩展功能
- 审计日志插件
- Doris On ES
- Doris output plugin
- ODBC External Table Of Doris
- Doris 插件框架
- Spark Doris Connector
- Flink Doris Connector
- DataX doriswriter
- UDF
设计文档
SQL 手册
- SQL 函数
- 日期函数
- convert_tz
- curdate
- current_timestamp
- curtime,current_time
- date_add
- date_format
- date_sub
- datediff
- day
- dayname
- dayofmonth
- dayofweek
- dayofyear
- from_days
- from_unixtime
- hour
- makedate
- minute
- month
- monthname
- now
- second
- strtodate
- time_round
- timediff
- timestampadd
- timestampdiff
- to_days
- unix_timestamp
- utc_timestamp
- week
- weekofyear
- year
- yearweek
- 地理位置函数
- 字符串函数
- 聚合函数
- bitmap 函数
- Hash函数
- Doris 窗口函数使用
- CAST
- DIGITAL_MASKING
- 日期函数
- 语法帮助
- 用户账户管理
- 集群管理
- ADMIN CANCEL REPAIR
- ADMIN CLEAN TRASH
- ADMIN CHECK TABLET
- ADMIN REPAIR
- ADMIN SET CONFIG
- ADMIN SET REPLICA STATUS
- ADMIN SHOW CONFIG
- ADMIN SHOW REPLICA DISTRIBUTION
- ADMIN SHOW REPLICA STATUS
- ADMIN SHOW DATA SKEW
- ALTER CLUSTER
- ALTER SYSTEM
- CANCEL DECOMMISSION
- CREATE CLUSTER
- CREATE FILE
- DROP CLUSTER
- DROP FILE
- ENTER
- INSTALL PLUGIN
- LINK DATABASE
- MIGRATE DATABASE
- SET LDAPADMINPASSWORD
- SHOW BACKENDS
- SHOW BROKER
- SHOW FILE
- SHOW FRONTENDS
- SHOW FULL COLUMNS
- SHOW INDEX
- SHOW MIGRATIONS
- SHOW PLUGINS
- SHOW TABLE STATUS
- SHOW TRASH
- UNINSTALL PLUGIN
- DDL
- ALTER DATABASE
- ALTER TABLE
- ALTER VIEW
- BACKUP
- CANCEL ALTER
- CANCEL BACKUP
- CANCEL RESTORE
- CREATE DATABASE
- CREATE ENCRYPTKEY
- CREATE INDEX
- CREATE MATERIALIZED VIEW
- CREATE REPOSITORY
- CREATE RESOURCE
- CREATE TABLE LIKE
- CREATE TABLE
- CREATE VIEW
- DROP DATABASE
- DROP ENCRYPTKEY
- DROP INDEX
- DROP MATERIALIZED VIEW
- DROP REPOSITORY
- DROP RESOURCE
- DROP TABLE
- DROP VIEW
- HLL
- RECOVER
- RESTORE
- SHOW ENCRYPTKEYS
- SHOW RESOURCES
- TRUNCATE TABLE
- CREATE FUNCTION
- DROP FUNCTION
- SHOW FUNCTIONS
- DML
- BROKER LOAD
- CANCEL LOAD
- DELETE
- EXPORT
- GROUP BY
- LOAD
- MINI LOAD
- MULTI LOAD
- PAUSE ROUTINE LOAD
- RESUME ROUTINE LOAD
- ROUTINE LOAD
- SHOW ALTER
- SHOW BACKUP
- SHOW CREATE FUNCTION
- SHOW CREATE ROUTINE LOAD
- SHOW DATA
- SHOW DATABASES
- SHOW DELETE
- SHOW DYNAMIC PARTITION TABLES
- SHOW EXPORT
- SHOW LOAD
- SHOW PARTITIONS
- SHOW PROPERTY
- SHOW REPOSITORIES
- SHOW RESTORE
- SHOW ROUTINE LOAD TASK
- SHOW ROUTINE LOAD
- SHOW SNAPSHOT
- SHOW TABLES
- SHOW TABLET
- SHOW TRANSACTION
- SPARK LOAD
- STOP ROUTINE LOAD
- STREAM LOAD
- ALTER ROUTINE LOAD
- INSERT
- UPDATE
- 数据类型
- 辅助命令
开发者手册
- 调试工具
- Doris BE存储层Benchmark工具
- 使用 Eclipse 搭建 FE 开发环境
- 使用 IntelliJ IDEA 搭建 FE 开发环境
- Apache Doris Be 开发调试
- Java 代码格式化
- C++ 代码格式化
Apache 社区
导入 Json 格式数据
Doris 从 0.12 版本开始支持 Json 格式的数据导入。
支持的导入方式
目前只有以下导入方式支持 Json 格式的数据导入:
- Stream Load
- Routine Load
关于以上导入方式的具体说明,请参阅相关文档。本文档主要介绍在这些导入方式中关于 Json 部分的使用说明。
支持的 Json 格式
当前前仅支持以下两种 Json 格式:
以 Array 表示的多行数据
以 Array 为根节点的 Json 格式。Array 中的每个元素表示要导入的一行数据,通常是一个 Object。示例如下:
[ { "id": 123, "city" : "beijing"}, { "id": 456, "city" : "shanghai"}, ... ]
[ { "id": 123, "city" : { "name" : "beijing", "region" : "haidian"}}, { "id": 456, "city" : { "name" : "beijing", "region" : "chaoyang"}}, ... ]
这种方式通常用于 Stream Load 导入方式,以便在一批导入数据中表示多行数据。
这种方式必须配合设置
strip_outer_array=true
使用。Doris在解析时会将数组展开,然后依次解析其中的每一个 Object 作为一行数据。以 Object 表示的单行数据
以 Object 为根节点的 Json 格式。整个 Object 即表示要导入的一行数据。示例如下:
{ "id": 123, "city" : "beijing"}
{ "id": 123, "city" : { "name" : "beijing", "region" : "haidian" }}
这种方式通常用于 Routine Load 导入方式,如表示 Kafka 中的一条消息,即一行数据。
Json Path
Doris 支持通过 Json Path 抽取 Json 中指定的数据。
注:因为对于 Array 类型的数据,Doris 会先进行数组展开,最终按照 Object 格式进行单行处理。所以本文档之后的示例都以单个 Object 格式的 Json 数据进行说明。
不指定 Json Path
如果没有指定 Json Path,则 Doris 会默认使用表中的列名查找 Object 中的元素。示例如下:
表中包含两列:
id
,city
Json 数据如下:
{ "id": 123, "city" : "beijing"}
则 Doris 会使用
id
,city
进行匹配,得到最终数据123
和beijing
。如果 Json 数据如下:
{ "id": 123, "name" : "beijing"}
则使用
id
,city
进行匹配,得到最终数据123
和null
。指定 Json Path
通过一个 Json 数据的形式指定一组 Json Path。数组中的每个元素表示一个要抽取的列。示例如下:
["$.id", "$.name"]
["$.id.sub_id", "$.name[0]", "$.city[0]"]
Doris 会使用指定的 Json Path 进行数据匹配和抽取。
匹配非基本类型
前面的示例最终匹配到的数值都是基本类型,如整型、字符串等。Doris 当前暂不支持复合类型,如 Array、Map 等。所以当匹配到一个非基本类型时,Doris 会将该类型转换为 Json 格式的字符串,并以字符串类型进行导入。示例如下:
Json 数据为:
{ "id": 123, "city" : { "name" : "beijing", "region" : "haidian" }}
Json Path 为
["$.city"]
。则匹配到的元素为:{ "name" : "beijing", "region" : "haidian" }
该元素会被转换为字符串进行后续导入操作:
"{'name':'beijing','region':'haidian'}"
匹配失败
当匹配失败时,将会返回
null
。示例如下:Json 数据为:
{ "id": 123, "name" : "beijing"}
Json Path 为
["$.id", "$.info"]
。则匹配到的元素为123
和null
。Doris 当前不区分 Json 数据中表示的 null 值,和匹配失败时产生的 null 值。假设 Json 数据为:
{ "id": 123, "name" : null }
则使用以下两种 Json Path 会获得相同的结果:
123
和null
。["$.id", "$.name"]
["$.id", "$.info"]
完全匹配失败
为防止一些参数设置错误导致的误操作。Doris 在尝试匹配一行数据时,如果所有列都匹配失败,则会认为这个是一个错误行。假设 Json 数据为:
{ "id": 123, "city" : "beijing" }
如果 Json Path 错误的写为(或者不指定 Json Path 时,表中的列不包含
id
和city
):["$.ad", "$.infa"]
则会导致完全匹配失败,则该行会标记为错误行,而不是产出
null, null
。
Json Path 和 Columns
Json Path 用于指定如何对 JSON 格式中的数据进行抽取,而 Columns 指定列的映射和转换关系。两者可以配合使用。
换句话说,相当于通过 Json Path,将一个 Json 格式的数据,按照 Json Path 中指定的列顺序进行了列的重排。之后,可以通过 Columns,将这个重排后的源数据和表的列进行映射。举例如下:
数据内容:
{"k1" : 1, "k2": 2}
表结构:
k2 int, k1 int
导入语句1(以 Stream Load 为例):
curl -v --location-trusted -u root: -H "format: json" -H "jsonpaths: [\"$.k2\", \"$.k1\"]" -T example.json http://127.0.0.1:8030/api/db1/tbl1/_stream_load
导入语句1中,仅指定了 Json Path,没有指定 Columns。其中 Json Path 的作用是将 Json 数据按照 Json Path 中字段的顺序进行抽取,之后会按照表结构的顺序进行写入。最终导入的数据结果如下:
+------+------+
| k1 | k2 |
+------+------+
| 2 | 1 |
+------+------+
会看到,实际的 k1 列导入了 Json 数据中的 "k2" 列的值。这是因为,Json 中字段名称并不等同于表结构中字段的名称。我们需要显式的指定这两者之间的映射关系。
导入语句2:
curl -v --location-trusted -u root: -H "format: json" -H "jsonpaths: [\"$.k2\", \"$.k1\"]" -H "columns: k2, k1" -T example.json http://127.0.0.1:8030/api/db1/tbl1/_stream_load
相比如导入语句1,这里增加了 Columns 字段,用于描述列的映射关系,按 k2, k1
的顺序。即按Json Path 中字段的顺序抽取后,指定第一列为表中 k2 列的值,而第二列为表中 k1 列的值。最终导入的数据结果如下:
+------+------+
| k1 | k2 |
+------+------+
| 1 | 2 |
+------+------+
当然,如其他导入一样,可以在 Columns 中进行列的转换操作。示例如下:
curl -v --location-trusted -u root: -H "format: json" -H "jsonpaths: [\"$.k2\", \"$.k1\"]" -H "columns: k2, tmp_k1, k1 = tmp_k1 * 100" -T example.json http://127.0.0.1:8030/api/db1/tbl1/_stream_load
上述示例会将 k1 的值乘以 100 后导入。最终导入的数据结果如下:
+------+------+
| k1 | k2 |
+------+------+
| 100 | 2 |
+------+------+
NULL 和 Default 值
示例数据如下:
[
{"k1": 1, "k2": "a"},
{"k1": 2},
{"k1": 3, "k2": "c"},
]
表结构为:k1 int null, k2 varchar(32) null default "x"
导入语句如下:
curl -v --location-trusted -u root: -H "format: json" -H "strip_outer_array: true" -T example.json http://127.0.0.1:8030/api/db1/tbl1/_stream_load
用户可能期望的导入结果如下,即对于缺失的列,填写默认值。
+------+------+
| k1 | k2 |
+------+------+
| 1 | a |
+------+------+
| 2 | x |
+------+------+
| 3 | c |
+------+------+
但实际的导入结果如下,即对于缺失的列,补上了 NULL。
+------+------+
| k1 | k2 |
+------+------+
| 1 | a |
+------+------+
| 2 | NULL |
+------+------+
| 3 | c |
+------+------+
这是因为通过导入语句中的信息,Doris 并不知道 “缺失的列是表中的 k2 列”。 如果要对以上数据按照期望结果导入,则导入语句如下:
curl -v --location-trusted -u root: -H "format: json" -H "strip_outer_array: true" -H "jsonpaths: [\"$.k1\", \"$.k2\"]" -H "columns: k1, tmp_k2, k2 = ifnull(tmp_k2, 'x')" -T example.json http://127.0.0.1:8030/api/db1/tbl1/_stream_load
LargetInt与Decimal
Doris支持LargeInt与Decimal等数据范围更大,数据精度更高的数据类型。但是由于Doris使用的Rapid Json库对于数字类型能够解析的最大范围为Int64与Double,这导致了通过Json导入LargeInt或Decimal时可能会出现:精度丢失,数据转换出错等问题。
示例数据如下:
[
{"k1": 1, "k2":9999999999999.999999 }
]
导入k2列类型为Decimal(16, 9)
,数据为:9999999999999.999999
。在进行Json导入时,由于Double转换的精度丢失导致了导入的数据为:10000000000000.0002
,引发了导入出错。
为了解决这个问题,Doris在导入时提供了 num_as_string
的开关。Doris在解析Json数据时会将数字类型转为字符串,然后在确保不会出现精度丢失的情况下进行导入。
curl -v --location-trusted -u root: -H "format: json" -H "num_as_string: true" -T example.json http://127.0.0.1:8030/api/db1/tbl1/_stream_load
但是开启这个开关会引起一些意想不到的副作用。Doris 当前暂不支持复合类型,如 Array、Map 等。所以当匹配到一个非基本类型时,Doris 会将该类型转换为 Json 格式的字符串,而num_as_string
会同样将复合类型的数字转换为字符串,举个例子:
Json 数据为:
{ "id": 123, "city" : { "name" : "beijing", "city_id" : 1 }}
不开启num_as_string
时,导入的city列的数据为:
{ "name" : "beijing", "city_id" : 1 }
而开启了num_as_string
时,导入的city列的数据为:
{ "name" : "beijing", "city_id" : "1" }
注意,这里导致了复合类型原先为1的数字类型的city_id被作为字符串列处理并添加上了引号,与原始数据相比,产生了变化。
所以用在使用Json导入时,要尽量避免LargeInt与Decimal与复合类型的同时导入。如果无法避免,则需要充分了解开启num_as_string
后对复合类型导入的副作用。
应用示例
Stream Load
因为 Json 格式的不可拆分特性,所以在使用 Stream Load 导入 Json 格式的文件时,文件内容会被全部加载到内存后,才开始处理。因此,如果文件过大的话,可能会占用较多的内存。
假设表结构为:
id INT NOT NULL,
city VARHCAR NULL,
code INT NULL
导入单行数据1
{"id": 100, "city": "beijing", "code" : 1}
不指定 Json Path
curl --location-trusted -u user:passwd -H "format: json" -T data.json http://localhost:8030/api/db1/tbl1/_stream_load
导入结果:
100 beijing 1
指定 Json Path
curl --location-trusted -u user:passwd -H "format: json" -H "jsonpaths: [\"$.id\",\"$.city\",\"$.code\"]" -T data.json http://localhost:8030/api/db1/tbl1/_stream_load
导入结果:
100 beijing 1
导入单行数据2
{"id": 100, "content": {"city": "beijing", "code" : 1}}
指定 Json Path
curl --location-trusted -u user:passwd -H "format: json" -H "jsonpaths: [\"$.id\",\"$.content.city\",\"$.content.code\"]" -T data.json http://localhost:8030/api/db1/tbl1/_stream_load
导入结果:
100 beijing 1
导入多行数据
[ {"id": 100, "city": "beijing", "code" : 1}, {"id": 101, "city": "shanghai"}, {"id": 102, "city": "tianjin", "code" : 3}, {"id": 103, "city": "chongqing", "code" : 4}, {"id": 104, "city": ["zhejiang", "guangzhou"], "code" : 5}, { "id": 105, "city": { "order1": ["guangzhou"] }, "code" : 6 } ]
指定 Json Path
curl --location-trusted -u user:passwd -H "format: json" -H "jsonpaths: [\"$.id\",\"$.city\",\"$.code\"]" -H "strip_outer_array: true" -T data.json http://localhost:8030/api/db1/tbl1/_stream_load
导入结果:
100 beijing 1 101 shanghai NULL 102 tianjin 3 103 chongqing 4 104 ["zhejiang","guangzhou"] 5 105 {"order1":["guangzhou"]} 6
对导入数据进行转换
数据依然是示例3中的多行数据,现需要对导入数据中的
code
列加1后导入。curl --location-trusted -u user:passwd -H "format: json" -H "jsonpaths: [\"$.id\",\"$.city\",\"$.code\"]" -H "strip_outer_array: true" -H "columns: id, city, tmpc, code=tmpc+1" -T data.json http://localhost:8030/api/db1/tbl1/_stream_load
导入结果:
100 beijing 2 101 shanghai NULL 102 tianjin 4 103 chongqing 5 104 ["zhejiang","guangzhou"] 6 105 {"order1":["guangzhou"]} 7
Routine Load
Routine Load 对 Json 数据的处理原理和 Stream Load 相同。在此不再赘述。
对于 Kafka 数据源,每个 Massage 中的内容被视作一个完整的 Json 数据。如果一个 Massage 中是以 Array 格式的表示的多行数据,则会导入多行,而 Kafka 的 offset 只会增加 1。而如果一个 Array 格式的 Json 表示多行数据,但是因为 Json 格式错误导致解析 Json 失败,则错误行只会增加 1(因为解析失败,实际上 Doris 无法判断其中包含多少行数据,只能按一行错误数据记录)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论