INSERT
将数据插入到指定的表中,或者使用数据覆盖指定的表。 从 v3.2.0 开始,INSERT 支持将数据写入到远程存储中的文件中。 您可以使用 INSERT INTO FILES() 从 StarRocks 卸载数据到远程存储。
您可以使用 SUBMIT TASK 提交异步 INSERT 任务。
语法
-
数据导入:
INSERT { INTO | OVERWRITE } [db_name.]<table_name>
[ PARTITION (<partition_name> [, ...] ) ]
[ TEMPORARY PARTITION (<temporary_partition_name> [, ...] ) ]
[ WITH LABEL <label>]
[ (<column_name>[, ...]) | BY NAME ]
[ PROPERTIES ("key"="value", ...) ]
{ VALUES ( { <expression> | DEFAULT } [, ...] ) | <query> } -
数据卸载:
INSERT INTO FILES()
[ WITH LABEL <label> ]
{ VALUES ( { <expression> | DEFAULT } [, ...] ) | <query> }
参数
参数 | 描述 |
---|---|
INTO | 将数据追加到表中。 |
OVERWRITE | 使用数据覆盖表。 |
table_name | 要加载数据的表的名称。 可以使用表所在的数据库指定,格式为 db_name.table_name 。 |
PARTITION | 要加载数据的分区。 可以指定多个分区,这些分区必须用逗号 (,) 分隔。 必须设置为目标表中存在的分区。 如果指定此参数,则数据将仅插入到指定的分区中。 如果不指定此参数,则数据将插入到所有分区中。 |
TEMPORARY PARTITION | 要加载数据的临时分区的名称。 可以指定多个临时分区,这些分区必须用逗号 (,) 分隔。 |
label | 数据库中每个数据加载事务的唯一标识标签。 如果未指定,系统会自动为事务生成一个。 我们建议您为事务指定标签。 否则,如果发生连接错误并且没有返回结果,则无法检查事务状态。 您可以通过 SHOW LOAD WHERE label="label" 语句检查事务状态。 有关标签的命名约定,请参阅系统限制。 |
column_name | 要加载数据的目标列的名称。 它必须设置为目标表中存在的列。 不能同时指定 column_name 和 BY NAME 。
从 v3.3.1 开始,在主键表上的 INSERT INTO 语句中指定列列表将执行部分更新(而不是早期版本中的完整 Upsert)。 如果未指定列列表,系统将执行完整 Upsert。 |
BY NAME | 按名称匹配源列和目标列。 不能同时指定 column_name 和 BY NAME 。 如果未指定,则无论目标列名是什么,目标列都会按顺序与源列一一映射。 |
PROPERTIES | INSERT 作业的属性。 每个属性必须是键值对。 有关支持的属性,请参阅PROPERTIES。 |
expression | 为列分配值的表达式。 |
DEFAULT | 为列分配默认值。 |
query | 查询语句,其结果将被加载到目标表中。 它可以是 StarRocks 支持的任何 SQL 语句。 |
FILES() | 表函数 FILES()。 您可以使用此函数将数据卸载到远程存储。 |
PROPERTIES
从 v3.4.0 开始,INSERT 语句支持配置 PROPERTIES。
属性 | 描述 |
---|---|
timeout | INSERT 作业的超时持续时间。 单位:秒。 您还可以使用变量 insert_timeout 在会话中或全局设置 INSERT 的超时持续时间。 |
strict_mode | 使用 FILES() 中的 INSERT 加载数据时是否启用严格模式。 有效值:true (默认)和 false 。 启用严格模式后,系统仅加载合格的行。 它会过滤掉不合格的行并返回有关不合格行的详细信息。 有关更多信息,请参阅严格模式。 您还可以使用变量 enable_insert_strict 在会话中或全局为 FILES() 中的 INSERT 启用严格模式。 |
max_filter_ratio | FILES() 中 INSERT 的最大错误容忍度。 它是由于数据质量不足而被过滤掉的数据记录的最大比率。 当不合格数据记录的比率达到此阈值时,作业将失败。 默认值:0 。 范围:[0, 1]。 您还可以使用变量 insert_max_filter_ratio 在会话中或全局设置 FILES() 中 INSERT 的最大错误容忍度。 |
strict_mode
和max_filter_ratio
仅支持 FILES() 中的 INSERT。 来自表的 INSERT 不支持这些属性。- 从 v3.4.0 开始,当
enable_insert_strict
设置为true
时,系统仅加载合格的行。 它会过滤掉不合格的行并返回有关不合格行的详细信息。 相反,在早于 v3.4.0 的版本中,当enable_insert_strict
设置为true
时,如果存在不合格的行,INSERT 作业将失败。
返回
Query OK, 5 rows affected, 2 warnings (0.05 sec)
{'label':'insert_load_test', 'status':'VISIBLE', 'txnId':'1008'}
返回 | 描述 |
---|---|
受影响的行数 | 指示加载了多少行。 warnings 指示被过滤掉的行。 |
label | 数据库中每个数据加载事务的唯一标识标签。 它可以由用户分配,也可以由系统自动分配。 |
status | 指示加载的数据是否可见。 VISIBLE :数据已成功加载并且可见。 COMMITTED :数据已成功加载,但目前不可见。 |
txnId | 与每个 INSERT 事务对应的 ID 号。 |
动态覆盖
从 v3.4.0 开始,StarRocks 支持一种新的语义 - 用于分区表的 INSERT OVERWRITE 的动态覆盖。
目前,INSERT OVERWRITE 的默认行为如下
- 当整体覆盖分区表时(即,不指定 PARTITION 子句),新的数据记录将替换其相应分区中的数据。 如果有未涉及的分区,它们将被截断,而其他分区将被覆盖。
- 当覆盖空分区表(即,其中没有分区)并指定 PARTITION 子句时,系统将返回错误
ERROR 1064 (HY000): Getting analyzing error. Detail message: Unknown partition 'xxx' in table 'yyy'
。 - 当覆盖分区表并在 PARTITION 子句中指定不存在的分区时,系统将返回错误
ERROR 1064 (HY000): Getting analyzing error. Detail message: Unknown partition 'xxx' in table 'yyy'
。 - 当使用与 PARTITION 子句中指定的任何分区都不匹配的数据记录覆盖分区表时,系统要么返回错误
ERROR 1064 (HY000): Insert has filtered data in strict mode
(如果启用了严格模式),要么过滤掉不合格的数据记录(如果禁用了严格模式)。
新的动态覆盖语义的行为大不相同
当整体覆盖分区表时,新的数据记录将替换其相应分区中的数据。 如果有未涉及的分区,它们将被保留,而不是被截断或删除。 并且如果有新的数据记录对应于不存在的分区,系统将创建该分区。
默认情况下禁用动态覆盖语义。 要启用它,您需要将系统变量 dynamic_overwrite
设置为 true
。
在当前会话中启用动态覆盖
SET dynamic_overwrite = true;
您也可以在 INSERT OVERWRITE 语句的提示中设置它,以使其仅对该语句生效:。
示例
INSERT /*+set_var(dynamic_overwrite = true)*/ OVERWRITE insert_wiki_edit
SELECT * FROM source_wiki_edit;
使用说明
-
对于当前版本,当 StarRocks 执行 INSERT INTO 语句时,如果任何数据行与目标表格式不匹配(例如,字符串太长),则默认情况下 INSERT 事务将失败。 您可以将会话变量
enable_insert_strict
设置为false
,以便系统过滤掉与目标表格式不匹配的数据并继续执行事务。 -
在执行 INSERT OVERWRITE 语句后,StarRocks 会为存储原始数据的分区创建临时分区,将数据插入到临时分区中,并将原始分区与临时分区交换。 所有这些操作都在 Leader FE 节点中执行。 因此,如果在执行 INSERT OVERWRITE 语句时 Leader FE 节点崩溃,则整个加载事务将失败,并且临时分区将被删除。
-
StarRocks 支持通过 INSERT OVERWRITE 语句写入非表达式分区。 但是,当将新数据写入先前不存在的分区时,系统将不会创建不存在的分区。
关于动态覆盖
- 动态覆盖仅支持表达式分区。 当将新数据写入先前不存在的分区时,系统将自动创建不存在的分区。
- 动态覆盖支持基于混合表达式的分区。
示例
示例 1:常规用法
以下示例基于表 test
,该表包含两列 c1
和 c2
。 c2
列的默认值为 DEFAULT。
- 将一行数据导入到
test
表中。
INSERT INTO test VALUES (1, 2);
INSERT INTO test (c1, c2) VALUES (1, 2);
INSERT INTO test (c1, c2) VALUES (1, DEFAULT);
INSERT INTO test (c1) VALUES (1);
如果未指定目标列,则默认情况下,列会按顺序加载到目标表中。 因此,在上面的示例中,第一个和第二个 SQL 语句的结果是相同的。
如果目标列(无论是否插入数据)使用 DEFAULT 作为值,则该列将使用默认值作为加载的数据。 因此,在上面的示例中,第三个和第四个语句的输出是相同的。
- 一次将多行数据加载到
test
表中。
INSERT INTO test VALUES (1, 2), (3, 2 + 2);
INSERT INTO test (c1, c2) VALUES (1, 2), (3, 2 * 2);
INSERT INTO test (c1, c2) VALUES (1, DEFAULT), (3, DEFAULT);
INSERT INTO test (c1) VALUES (1), (3);
因为表达式的结果是等效的,所以第一个和第二个语句的结果是相同的。 第三个和第四个语句的结果是相同的,因为它们都使用默认值。
- 将查询语句结果导入到
test
表中。
INSERT INTO test SELECT * FROM test2;
INSERT INTO test (c1, c2) SELECT * from test2;
- 将查询结果导入到
test
表中,并指定分区和标签。
INSERT INTO test PARTITION(p1, p2) WITH LABEL `label1` SELECT * FROM test2;
INSERT INTO test WITH LABEL `label1` (c1, c2) SELECT * from test2;
- 使用查询结果覆盖
test
表,并指定分区和标签。
INSERT OVERWRITE test PARTITION(p1, p2) WITH LABEL `label1` SELECT * FROM test3;
INSERT OVERWRITE test WITH LABEL `label1` (c1, c2) SELECT * from test3;
示例 2:使用 FILES() 中的 INSERT 从 AWS S3 加载 Parquet 文件
以下示例将 AWS S3 存储桶 inserttest
中的 Parquet 文件 parquet/insert_wiki_edit_append.parquet 中的数据行插入到表 insert_wiki_edit
中
INSERT INTO insert_wiki_edit
SELECT * FROM FILES(
"path" = "s3://inserttest/parquet/insert_wiki_edit_append.parquet",
"format" = "parquet",
"aws.s3.access_key" = "XXXXXXXXXX",
"aws.s3.secret_key" = "YYYYYYYYYY",
"aws.s3.region" = "ap-southeast-1"
);
示例 3:INSERT 超时
以下示例将源表 source_wiki_edit
中的数据插入到目标表 insert_wiki_edit
中,超时持续时间设置为 2
秒。
INSERT INTO insert_wiki_edit
PROPERTIES(
"timeout" = "2"
)
SELECT * FROM source_wiki_edit;
如果要摄取大型数据集,可以为 timeout
设置更大的值,或者为会话变量 insert_timeout
设置更大的值。
示例 4:INSERT 严格模式和最大过滤比率
以下示例将 AWS S3 存储桶 inserttest
中的 Parquet 文件 parquet/insert_wiki_edit_append.parquet 中的数据行插入到表 insert_wiki_edit
中,启用严格模式以过滤掉不合格的数据记录,并容忍最多 10% 的错误数据
INSERT INTO insert_wiki_edit
PROPERTIES(
"strict_mode" = "true",
"max_filter_ratio" = "0.1"
)
SELECT * FROM FILES(
"path" = "s3://inserttest/parquet/insert_wiki_edit_append.parquet",
"format" = "parquet",
"aws.s3.access_key" = "XXXXXXXXXX",
"aws.s3.secret_key" = "YYYYYYYYYY",
"aws.s3.region" = "us-west-2"
);
示例 5:INSERT 按名称匹配列
以下示例按名称匹配源表和目标表中的每一列
INSERT INTO insert_wiki_edit BY NAME
SELECT event_time, user, channel FROM source_wiki_edit;
在这种情况下,更改 channel
和 user
的顺序不会更改列映射。