跳到主要内容
版本:26.x

Insert Into Values

INSERT INTO VALUES 语句支持将 SQL 中的内联值导入到 Doris 的表中,是一种同步导入方式,执行后会直接返回导入结果,可以根据返回内容判断导入是否成功。该方式保证导入任务的原子性:要么全部成功,要么全部失败。

使用场景​

INSERT INTO VALUES 主要面向以下两类场景:

场景说明
功能验证 / Demo仅导入少量假数据以验证 Doris 系统的功能,语法与 MySQL 一致
小批量数据写入在并发较低、数据量较小的场景下使用
性能提示

并发的 INSERT INTO VALUES 性能会受到 commit 阶段瓶颈的限制。当导入数据量较大时,建议开启 Group Commit 以获得更高吞吐。

基本原理​

INSERT INTO VALUES 通过 MySQL 协议将作业发送给 FE 节点执行,整体流程如下:

  1. 客户端通过 MySQL 协议向 FE 提交 INSERT INTO VALUES 语句。
  2. FE 生成执行计划:前部为查询相关的算子,最后一个算子为 OlapTableSink,负责将查询结果写入目标表。
  3. FE 将执行计划下发给 BE 节点执行,并选定一个 BE 作为 Coordinator 节点。
  4. Coordinator 节点负责接收数据,并将数据分发到其他 BE 节点完成写入。

快速上手​

INSERT INTO VALUES 通过 MySQL 协议提交和传输。下例以 MySQL 命令行为例,演示完整的提交流程。详细语法请参见 INSERT INTO。

前置检查​

执行 INSERT INTO VALUES 需要对目标表具有 INSERT 权限。如果当前用户没有该权限,可使用 GRANT 命令进行授权。

创建导入作业​

步骤 1:创建目标表​

CREATE TABLE testdb.test_table(
user_id BIGINT NOT NULL COMMENT "user id",
name VARCHAR(20) COMMENT "name",
age INT COMMENT "age"
)
DUPLICATE KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 10;

步骤 2:执行 INSERT INTO VALUES 写入数据​

不推荐在生产环境中使用

INSERT INTO VALUES 一般仅用于 Demo 或测试,不建议用于生产环境的数据导入。

INSERT INTO testdb.test_table (user_id, name, age)
VALUES (1, "Emily", 25),
(2, "Benjamin", 35),
(3, "Olivia", 28),
(4, "Alexander", 60),
(5, "Ava", 17);

作为同步导入方式,结果会直接返回给客户端:

Query OK, 5 rows affected (0.308 sec)
{'label':'label_26eebc33411f441c_b2b286730d495e2c', 'status':'VISIBLE', 'txnId':'61071'}

步骤 3:校验导入数据​

MySQL> SELECT COUNT(*) FROM testdb.test_table;
+----------+
| count(*) |
+----------+
| 5 |
+----------+
1 row in set (0.179 sec)

查看导入作业​

可通过 SHOW LOAD 命令查看已完成的 INSERT INTO VALUES 作业:

mysql> SHOW LOAD FROM testdb\G
*************************** 1. row ***************************
JobId: 77172
Label: label_26eebc33411f441c_b2b286730d495e2c
State: FINISHED
Progress: Unknown id: 77172
Type: INSERT
EtlInfo: NULL
TaskInfo: cluster:N/A; timeout(s):14400; max_filter_ratio:0.0
ErrorMsg: NULL
CreateTime: 2024-11-20 16:44:08
EtlStartTime: 2024-11-20 16:44:08
EtlFinishTime: 2024-11-20 16:44:08
LoadStartTime: 2024-11-20 16:44:08
LoadFinishTime: 2024-11-20 16:44:08
URL:
JobDetails: {"Unfinished backends":{},"ScannedRows":0,"TaskNumber":0,"LoadBytes":0,"All backends":{},"FileNumber":0,"FileSize":0}
TransactionId: 61071
ErrorTablets: {}
User: root
Comment:
1 row in set (0.00 sec)

取消导入作业​

在 MySQL 客户端中,可以使用 Ctrl-C 取消当前正在执行的 INSERT INTO VALUES 作业。

参考手册​

导入命令语法​

INSERT INTO target_table (col1, col2, ...)
VALUES (val1, val2, ...), (val3, val4, ...), ...;
备注

INSERT INTO VALUES 一般仅用于 Demo,不建议在生产环境使用。

导入配置参数​

FE 配置​

参数默认值描述
insert_load_default_timeout_second14400(4 小时)导入任务的超时时间,单位:秒。导入任务在该超时时间内未完成则会被系统取消,状态变为 CANCELLED

环境变量(Session Variables)​

参数默认值描述
insert_timeout14400(4 小时)INSERT INTO 作为 SQL 语句执行时的超时时间,单位:秒
enable_insert_stricttrue取值为 true 时,遇到不合格数据则导入失败;取值为 false 时,忽略不合格行,只要有一条数据被正确导入,导入即视为成功。在 2.1.4 及以前的版本中,INSERT INTO 无法控制错误率,只能通过该参数设置为严格检查数据质量或完全忽略错误数据
insert_max_filter_ratio1.0自 2.1.5 版本起支持,仅在 enable_insert_strict=false 时生效。用于控制 INSERT INTO FROM S3/HDFS/LOCAL() 时的错误容忍率,取值范围 0 ~ 1。默认 1.0 表示容忍所有错误;当错误行数比例超过该值时 INSERT 任务会失败
数据不合格的常见原因

源数据列长度超过目的数据列长度、列类型不匹配、分区不匹配、列顺序不匹配等。

导入返回值​

INSERT INTO VALUES 是一个 SQL 语句,返回结果中包含一个 JSON 字符串,字段含义如下:

参数名称说明
Label导入作业的 label,可通过 INSERT INTO tbl WITH LABEL label ... 指定
Status导入数据的可见状态:
- visible:导入成功,数据可见
- committed:导入已完成,数据可能延迟可见,无需重试
- Label Already Exists:Label 重复,需要更换
- Fail:导入失败
Err导入错误信息
TxnId导入事务的 ID

下面分别给出四种典型返回场景的示例。

场景 1:INSERT 执行成功​

mysql> INSERT INTO test_table (user_id, name, age) VALUES (1, "Emily", 25), (2, "Benjamin", 35), (3, "Olivia", 28), (NULL, "Alexander", 60), (5, "Ava", 17);
Query OK, 5 rows affected (0.05 sec)
{'label':'label_26eebc33411f441c_b2b286730d495e2c', 'status':'VISIBLE', 'txnId':'61071'}
  • Query OK:表示语句执行成功
  • 5 rows affected:表示总共有 5 行数据被导入

场景 2:INSERT 执行成功但有 warning​

mysql> INSERT INTO test_table (user_id, name, age) VALUES (1, "Emily", 25), (2, "Benjamin", 35), (3, "Olivia", 28), (NULL, "Alexander", 60), (5, "Ava", 17);
Query OK, 4 rows affected, 1 warning (0.04 sec)
{'label':'label_a8d99ae931194d2b_93357aac59981a18', 'status':'VISIBLE', 'txnId':'61068'}
  • Query OK:表示语句执行成功
  • 4 rows affected:表示总共有 4 行数据被导入
  • 1 warnings:表示被过滤了 1 行

可通过 SHOW LOAD 语句查看被过滤的行。返回结果中的 URL 可用于查询错误数据,详见下文 查看错误行。

mysql> SHOW LOAD WHERE label="label_a8d99ae931194d2b_93357aac59981a18"\G
*************************** 1. row ***************************
JobId: 77158
Label: label_a8d99ae931194d2b_93357aac59981a18
State: FINISHED
Progress: Unknown id: 77158
Type: INSERT
EtlInfo: NULL
TaskInfo: cluster:N/A; timeout(s):14400; max_filter_ratio:0.0
ErrorMsg: NULL
CreateTime: 2024-11-20 16:35:40
EtlStartTime: 2024-11-20 16:35:40
EtlFinishTime: 2024-11-20 16:35:40
LoadStartTime: 2024-11-20 16:35:40
LoadFinishTime: 2024-11-20 16:35:40
URL: http://10.16.10.7:8743/api/_load_error_log?file=__shard_18/error_log_insert_stmt_a8d99ae931194d2b-93357aac59981a19_a8d99ae931194d2b_93357aac59981a19
JobDetails: {"Unfinished backends":{},"ScannedRows":0,"TaskNumber":0,"LoadBytes":0,"All backends":{},"FileNumber":0,"FileSize":0}
TransactionId: 61068
ErrorTablets: {}
User: root
Comment:
1 row in set (0.00 sec)

场景 3:INSERT 执行成功但 status 为 committed​

mysql> INSERT INTO test_table (user_id, name, age) VALUES (1, "Emily", 25), (2, "Benjamin", 35), (3, "Olivia", 28), (4, "Alexander", 60), (5, "Ava", 17);
Query OK, 5 rows affected (0.04 sec)
{'label':'label_78bf5396d9594d4d_a8d9a914af40f73d', 'status':'COMMITTED', 'txnId':'61074'}

数据不可见是临时状态,这批数据最终一定会变为可见。可通过 SHOW TRANSACTION 语句查看可见状态,当 TransactionStatus 列变为 VISIBLE 时即代表数据可见。

mysql> SHOW TRANSACTION WHERE id=61074\G
*************************** 1. row ***************************
TransactionId: 61074
Label: label_78bf5396d9594d4d_a8d9a914af40f73d
Coordinator: FE: 10.16.10.7
TransactionStatus: VISIBLE
LoadJobSourceType: INSERT_STREAMING
PrepareTime: 2024-11-20 16:51:54
PreCommitTime: NULL
CommitTime: 2024-11-20 16:51:54
PublishTime: 2024-11-20 16:51:54
FinishTime: 2024-11-20 16:51:54
Reason:
ErrorReplicasCount: 0
ListenerId: -1
TimeoutMs: 14400000
ErrMsg:
1 row in set (0.00 sec)

场景 4:INSERT 执行失败​

执行失败表示没有任何数据被成功导入:

mysql> INSERT INTO test_table (user_id, name, age) VALUES (1, "Emily", 25), (2, "Benjamin", 35), (3, "Olivia", 28), (NULL, "Alexander", 60), (5, "Ava", 17);
ERROR 1105 (HY000): errCode = 2, detailMessage = Insert has too many filtered data 1/5 insert_max_filter_ratio is 0.100000. url: http://10.16.10.7:8747/api/_load_error_log?file=__shard_22/error_log_insert_stmt_5fafe6663e1a45e0-a666c1722ffc8c55_5fafe6663e1a45e0_a666c1722ffc8c55
  • ERROR 1105 (HY000): errCode = 2, detailMessage = Insert has too many filtered data 1/5 insert_max_filter_ratio is 0.100000. 显示失败原因
  • 末尾的 url 可用于查询错误数据,详见下文 查看错误行

导入最佳实践​

数据量​

INSERT INTO VALUES 通常用于测试和演示,不建议用于导入大量数据的场景。如有大批量写入需求,建议使用 Group Commit 或其他批量导入方式。

查看错误行​

当 INSERT INTO 返回结果中提供了 url 字段时,可通过以下命令查看错误行:

SHOW LOAD WARNINGS ON "url";

示例:

mysql> SHOW LOAD WARNINGS ON "http://10.16.10.7:8743/api/_load_error_log?file=__shard_18/error_log_insert_stmt_a8d99ae931194d2b-93357aac59981a19_a8d99ae931194d2b_93357aac59981a19"\G
*************************** 1. row ***************************
JobId: -1
Label: NULL
ErrorMsgDetail: Reason: column_name[user_id], null value for not null column, type=BIGINT. src line [];
1 row in set (0.00 sec)

常见错误原因包括:

  • 源数据列长度超过目的数据列长度
  • 列类型不匹配
  • 分区不匹配
  • 列顺序不匹配

可通过环境变量 enable_insert_strict 控制 INSERT INTO 是否忽略错误行。

常见问题(FAQ)​

Q1:INSERT INTO VALUES 是同步还是异步导入?

A:同步导入。语句执行完成后会直接返回导入结果,无需额外轮询。

Q2:INSERT INTO VALUES 能保证原子性吗?

A:可以。一次 INSERT INTO VALUES 的所有数据要么全部导入成功,要么全部失败,不会出现部分写入。

Q3:返回 status 为 COMMITTED 是导入失败了吗?

A:不是。COMMITTED 表示导入已完成,数据稍后会变为可见,无需重试。可通过 SHOW TRANSACTION 查看 TransactionStatus 直到变为 VISIBLE。

Q4:为什么导入后报 Insert has too many filtered data?

A:当 enable_insert_strict=false 时,被过滤的数据比例超过了 insert_max_filter_ratio 设置的阈值。可放宽 insert_max_filter_ratio,或检查源数据是否符合表结构(列类型、是否允许 NULL 等)。

Q5:大批量导入应该使用什么方式?

A:INSERT INTO VALUES 在高并发或大数据量场景下会受到 commit 瓶颈限制,建议开启 Group Commit,或选择 Stream Load、Broker Load 等专用导入方式。

故障排查(Troubleshooting)​

问题现象可能原因解决方案
报错 null value for not null column向 NOT NULL 列插入了 NULL 值修正源数据,或调整目标列为允许 NULL
报错 Insert has too many filtered data过滤行比例超出 insert_max_filter_ratio提高 insert_max_filter_ratio 阈值,或修正源数据
报错 Label Already Exists指定的 Label 已被使用更换 Label,或不指定 Label 让系统自动生成
任务长时间未完成被取消超过 insert_load_default_timeout_second 或 insert_timeout调大对应超时参数,或拆分批次导入
高并发下吞吐不高受 commit 阶段瓶颈限制开启 Group Commit

更多帮助​

关于 INSERT INTO 使用的更多详细语法,请参阅 INSERT INTO 命令手册,也可以在 MySQL 客户端命令行下输入 HELP INSERT 获取更多帮助信息。