跳到主要内容
跳到主要内容

INSERT-OVERWRITE

INSERT OVERWRITE

Name

INSERT OVERWRITE

Description

该语句的功能是重写表或表的某些分区

INSERT OVERWRITE table table_name
[ PARTITION (p1, ...) ]
[ WITH LABEL label]
[ (column [, ...]) ]
[ [ hint [, ...] ] ]
{ VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }

Parameters

table_name: 需要重写的目的表。这个表必须存在。可以是 db_name.table_name 形式

partitions: 需要重写的表分区,必须是 table_name 中存在的分区,多个分区名称用逗号分隔

label: 为 Insert 任务指定一个 label

column_name: 指定的目的列,必须是 table_name 中存在的列

expression: 需要赋值给某个列的对应表达式

DEFAULT: 让对应列使用默认值

query: 一个普通查询,查询的结果会重写到目标中

hint: 用于指示 INSERT 执行行为的一些指示符。目前 hint 有三个可选值/*+ STREAMING *//*+ SHUFFLE *//*+ NOSHUFFLE */

  1. STREAMING:目前无实际作用,只是为了兼容之前的版本,因此保留。(之前的版本加上这个 hint 会返回 label,现在默认都会返回 label)
  2. SHUFFLE:当目标表是分区表,开启这个 hint 会进行 repartiiton。
  3. NOSHUFFLE:即使目标表是分区表,也不会进行 repartiiton,但会做一些其他操作以保证数据正确落到各个分区中。

注意:

在当前版本中,会话变量 enable_insert_strict 默认为 true,如果执行 INSERT OVERWRITE 语句时,对于有不符合目标表格式的数据被过滤掉的话会重写目标表失败(比如重写分区时,不满足所有分区条件的数据会被过滤)。

INSERT OVERWRITE语句会首先创建一个新表,将需要重写的数据插入到新表中,最后原子性的用新表替换旧表并修改名称。因此,在重写表的过程中,旧表中的数据在重写完毕之前仍然可以正常访问。

Example

假设有test 表。该表包含两个列c1, c2,两个分区p1,p2。建表语句如下所示

CREATE TABLE IF NOT EXISTS test (
`c1` int NOT NULL DEFAULT "1",
`c2` int NOT NULL DEFAULT "4"
) ENGINE=OLAP
UNIQUE KEY(`c1`)
PARTITION BY LIST (`c1`)
(
PARTITION p1 VALUES IN ("1","2","3"),# 分区p1只允许1 2 3存在
PARTITION p2 VALUES IN ("4","5","6") # 分区p2只允许1 5 6存在
)
DISTRIBUTED BY HASH(`c1`) BUCKETS 3
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"in_memory" = "false",
"storage_format" = "V2"
);

Overwrite Table

  1. VALUES的形式重写test

    # 单行重写
    INSERT OVERWRITE table test VALUES (1, 2);
    INSERT OVERWRITE table test (c1, c2) VALUES (1, 2);
    INSERT OVERWRITE table test (c1, c2) VALUES (1, DEFAULT);
    INSERT OVERWRITE table test (c1) VALUES (1);
    # 多行重写
    INSERT OVERWRITE table test VALUES (1, 2), (3, 2 + 2);
    INSERT OVERWRITE table test (c1, c2) VALUES (1, 2), (3, 2 * 2);
    INSERT OVERWRITE table test (c1, c2) VALUES (1, DEFAULT), (3, DEFAULT);
    INSERT OVERWRITE table test (c1) VALUES (1), (3);
  • 第一条语句和第二条语句的效果一致,重写时如果不指定目标列,会使用表中的列顺序来作为默认的目标列。重写成功后表test中只有一行数据。

  • 第三条语句和第四条语句的效果一致,没有指定的列c2会使用默认值4来完成数据重写。重写成功后表test中只有一行数据。

  • 第五条语句和第六条语句的效果一致,在语句中可以使用表达式(如2+22*2),执行语句的时候会计算出表达式的结果再重写表test。重写成功后表test中有两行数据。

  • 第七条语句和第八条语句的效果一致,没有指定的列c2会使用默认值4来完成数据重写。重写成功后表test中有两行数据。

  1. 查询语句的形式重写test表,表test2和表test的数据格式需要保持一致,如果不一致会触发数据类型的隐式转换

    INSERT OVERWRITE table test SELECT * FROM test2;
    INSERT OVERWRITE table test (c1, c2) SELECT * from test2;
  • 第一条语句和第二条语句的效果一致,该语句的作用是将数据从表test2中取出,使用取出的数据重写表test。重写成功后表test中的数据和表test2中的数据保持一致。
  1. 重写 test 表并指定label

    INSERT OVERWRITE table test WITH LABEL `label1` SELECT * FROM test2;
    INSERT OVERWRITE table test WITH LABEL `label2` (c1, c2) SELECT * from test2;
  • 使用label会将此任务封装成一个异步任务,执行语句之后,相关操作都会异步执行,用户可以通过SHOW LOAD;命令查看此label导入作业的状态。需要注意的是label具有唯一性。

Overwrite Table Partition

使用 INSERT OVERWRITE 重写分区时,实际我们是将如下三步操作封装为一个事务并执行,如果中途失败,已进行的操作将会回滚:

  1. 假设指定重写分区 p1,首先创建一个与重写的目标分区结构相同的空临时分区 pTMP
  2. pTMP 中写入数据
  3. 使用 pTMP 原子替换 p1 分区

举例如下:

  1. VALUES的形式重写test表分区P1p2

    # 单行重写
    INSERT OVERWRITE table test PARTITION(p1,p2) VALUES (1, 2);
    INSERT OVERWRITE table test PARTITION(p1,p2) (c1, c2) VALUES (1, 2);
    INSERT OVERWRITE table test PARTITION(p1,p2) (c1, c2) VALUES (1, DEFAULT);
    INSERT OVERWRITE table test PARTITION(p1,p2) (c1) VALUES (1);
    # 多行重写
    INSERT OVERWRITE table test PARTITION(p1,p2) VALUES (1, 2), (4, 2 + 2);
    INSERT OVERWRITE table test PARTITION(p1,p2) (c1, c2) VALUES (1, 2), (4, 2 * 2);
    INSERT OVERWRITE table test PARTITION(p1,p2) (c1, c2) VALUES (1, DEFAULT), (4, DEFAULT);
    INSERT OVERWRITE table test PARTITION(p1,p2) (c1) VALUES (1), (4);

    以上语句与重写表不同的是,它们都是重写表中的分区。分区可以一次重写一个分区也可以一次重写多个分区。需要注意的是,只有满足对应分区过滤条件的数据才能够重写成功。如果重写的数据中有数据不满足其中任意一个分区,那么本次重写会失败。一个失败的例子如下所示

    INSERT OVERWRITE table test PARTITION(p1,p2) VALUES (7, 2);

    以上语句重写的数据c1=7分区p1p2的条件都不满足,因此会重写失败。

  2. 查询语句的形式重写test表分区P1p2,表test2和表test的数据格式需要保持一致,如果不一致会触发数据类型的隐式转换

    INSERT OVERWRITE table test PARTITION(p1,p2) SELECT * FROM test2;
    INSERT OVERWRITE table test PARTITION(p1,p2) (c1, c2) SELECT * from test2;
  3. 重写 test 表分区P1p2并指定label

    INSERT OVERWRITE table test PARTITION(p1,p2) WITH LABEL `label3` SELECT * FROM test2;
    INSERT OVERWRITE table test PARTITION(p1,p2) WITH LABEL `label4` (c1, c2) SELECT * from test2;

Keywords

INSERT OVERWRITE