CLONE TABLE

更新时间:
复制为 MD 格式

CLONE TABLE支持高效地将源表数据复制到目标表中,适用于表数据迁移场景。本文以具体示例介绍如何使用CLONE TABLE功能。

适用范围

  • Schema兼容性:目标表需兼容源表的Schema。

  • 分区数量限制

    • 目标表已存在时,单次最多可复制10,000个分区。

    • 目标表不存在时,无分区数量限制,满足原子性。

  • 支持表类型

    • PK/Append Delta Table

      不支持覆盖已有的 Delta Table,只能通过 CLONE TABLE 创建新的 Delta Table。

    • 普通表(分区表、非分区表、聚簇表)

    • Transactional 表

      不支持覆盖已有的 Transactional 表,只能通过 CLONE TABLE 创建新的 Transactional 表。

  • 外部表限制:不支持对外部表使用CLONE TABLE命令复制表数据。

  • 行级权限或数据脱敏策略

    不支持对设置了行级访问策略(Row Access Policy)或数据脱敏策略(Data Masking Policy)的表执行 CLONE TABLE。

  • 跨区域限制:不支持在跨地域或跨集群(项目运维迁移期间)的MaxCompute项目之间使用CLONE TABLE命令复制表数据。

  • 跨存储类型限制

    不支持在跨不同存储类型的项目之间使用CLONE TABLE命令复制表数据,例如多 AZ 存储项目与单 AZ 存储项目之间互相克隆。

    • 跨不同存储类型的项目之间复制表推荐方案:

      • 非分区表采用CREATE TABLE AS方式迁移数据。

      • 分区表通过CREATE TABLE LIKE先建表,然后执行INSERT OVERWRITE迁移数据。

  • 不支持对已进行Schema Evolution(例如增删列)的表执行ClONE操作。

费用说明

CLONE TABLE 是基于元数据的操作,不产生计算费用。克隆生成的目标表会按实际存储量计费。

命令格式

CLONE TABLE <[<src_project_name>.]<src_table_name>> [PARTITION(<pt_spec>), ...]
 TO <[<dest_project_name>.]<dest_table_name>> [IF EXISTS [OVERWRITE | IGNORE]] ;

参数说明

参数

是否必填

说明

src_project_name

源表所属MaxCompute项目名称。不指定时,默认为当前项目。当源表与目标表不属于同一个MaxCompute项目时,需要携带此参数。

src_table_name

源表名称。

pt_spec

源表的分区信息。

格式为:(partition_col1 = partition_col_value1, partition_col2 = partition_col_value2, ...)。其中partition_col是分区字段,partition_col_value是分区值。

dest_project_name

目标表所属MaxCompute项目名称。不指定时,默认为当前项目。当目标表与源表不属于同一个MaxCompute项目时,需要携带此参数。

dest_table_name

目标表名称。

  • 当目标表不存在时,CLONE TABLE命令会创建目标表,创建目标表使用的是CREATE TABLE LIKE语义。更多CREATE TABLE LIKE信息,请参见创建和删除表

  • 当目标表已存在并指定IF EXISTS OVERWRITE时,CLONE TABLE命令会覆盖目标表或对应分区的数据。

  • 当目标表已存在并指定IF EXISTS IGNORE时,CLONE TABLE命令会跳过已存在分区,不会覆盖目标表已有分区的数据。

示例数据

为便于理解,本文提供源数据,并基于源数据提供相关示例。分别创建分区表sale_detail和非分区表sale_detail_np,并添加数据,命令示例如下:

分区表sale_detail

  1. 创建分区表

    -- 创建一张分区表sale_detail。
    CREATE TABLE IF NOT EXISTS sale_detail
    (
    shop_name     string,
    customer_id   string,
    total_price   double
    )
    PARTITIONED BY (sale_date string, region string);
    
    -- 向源表增加分区。
    ALTER TABLE sale_detail ADD PARTITION (sale_date='2013', region='china') PARTITION (sale_date='2014', region='shanghai');
    
    -- 向源表追加数据。
    INSERT INTO sale_detail PARTITION (sale_date='2013', region='china') VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);
    INSERT INTO sale_detail PARTITION (sale_date='2014', region='shanghai') VALUES ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
  2. 查询分区表sale_detail中的数据,命令示例如下:

    -- 开启全表扫描,仅此Session有效。执行select语句查看表sale_detail中的数据。
    SET odps.sql.allow.fullscan=true; 
    SELECT * FROM sale_detail;

    单击查看返回结果

    -- 返回结果如下:
    +------------+-------------+-------------+------------+------------+
    | shop_name  | customer_id | total_price | sale_date  | region     |
    +------------+-------------+-------------+------------+------------+
    | s1         | c1          | 100.1       | 2013       | china      |
    | s2         | c2          | 100.2       | 2013       | china      |
    | s3         | c3          | 100.3       | 2013       | china      |
    | null       | c5          | NULL        | 2014       | shanghai   |
    | s6         | c6          | 100.4       | 2014       | shanghai   |
    | s7         | c7          | 100.5       | 2014       | shanghai   |
    +------------+-------------+-------------+------------+------------+

非分区表sale_detail_np

  1. 创建非分区表

    -- 创建一张非分区表sale_detail_np。
    CREATE TABLE IF NOT EXISTS sale_detail_np
    (
    shop_name     string,
    customer_id   string,
    total_price   double
    );
    
    -- 向源表追加数据。
    INSERT INTO sale_detail_np VALUES ('s4','c4',100.4);
  2. 查询非分区表sale_detail_np中的数据,命令示例如下:

    SELECT * FROM sale_detail_np;

    单击查看返回结果

    -- 返回结果如下:
    +------------+-------------+-------------+
    | shop_name  | customer_id | total_price |
    +------------+-------------+-------------+
    | s4         | c4          | 100.4       |
    +------------+-------------+-------------+

使用示例

基于示例数据,CLONE TABLE命令的使用示例如下:

示例一:将非分区表数据全量复制到目标表

全量复制非分区表sale_detail_np的数据至目标表sale_detail_np_clone。

-- 复制表数据。
CLONE TABLE sale_detail_np TO sale_detail_np_clone;
-- 查看复制后目标表sale_detail_np_clone的信息,验证数据准确性。
SELECT * FROM sale_detail_np_clone;

单击查看返回结果

-- 返回结果如下:
+------------+-------------+-------------+
| shop_name  | customer_id | total_price |
+------------+-------------+-------------+
| s4         | c4          | 100.4       |
+------------+-------------+-------------+

示例二:将分区表指定分区数据复制到目标表

复制分区表sale_detail指定分区的数据至目标表sale_detail_clone。

-- 复制表数据
CLONE TABLE sale_detail PARTITION (sale_date='2013', region='china') TO sale_detail_clone IF EXISTS OVERWRITE;

-- 开启全表扫描,执行select语句查看复制后目标表sale_detail_clone的信息,验证数据准确性。
SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail_clone;

单击查看返回结果

-- 返回结果如下:
+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
+------------+-------------+-------------+------------+------------+

示例三:将分区表数据全量复制到目标表并跳过目标表中已存在的分区

全量复制分区表sale_detail的数据至目标表sale_detail_clone(示例2已生成的表)并跳过目标表中已存在的分区。

-- 复制表数据。
CLONE TABLE sale_detail TO sale_detail_clone IF EXISTS IGNORE;

-- 查看复制后目标表sale_detail_clone的信息,验证数据准确性。
-- 开启全表扫描,仅此Session有效。执行select语句查看表sale_detail_clone中的数据。
SET odps.sql.allow.fullscan=true; 
SELECT * FROM sale_detail_clone;

单击查看返回结果

-- 返回结果如下:
+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
| null       | c5          | NULL        | 2014       | shanghai   |
| s6         | c6          | 100.4       | 2014       | shanghai   |
| s7         | c7          | 100.5       | 2014       | shanghai   |
+------------+-------------+-------------+------------+------------+

示例四:将分区表数据全量复制到目标表

全量复制分区表sale_detail的数据至目标表sale_detail_clone1。

-- 复制表数据。
CLONE TABLE sale_detail TO sale_detail_clone1;

-- 开启全表扫描,执行select语句查看复制后目标表sale_detail_clone1的信息,验证数据准确性。
SET odps.sql.allow.fullscan=true; 
SELECT * FROM sale_detail_clone1;

单击查看返回结果

-- 返回结果如下:
+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
| null       | c5          | NULL        | 2014       | shanghai   |
| s6         | c6          | 100.4       | 2014       | shanghai   |
| s7         | c7          | 100.5       | 2014       | shanghai   |
+------------+-------------+-------------+------------+------------+

示例五:克隆Delta Table

  • 克隆Delta Table非分区表

    -- 新建Delta Table非分区表
    CREATE TABLE IF NOT EXISTS sale_detail_delta                                        
      (                                                                                   
        shop_name     STRING,                                                             
        customer_id   STRING,
        total_price   DOUBLE
      )
      TBLPROPERTIES ("table.format.version"="2");
    
    INSERT INTO sale_detail_delta VALUES ('s1','c1',100.1),('s2','c2',100.2);
    
    -- 克隆示例                             
    CLONE TABLE sale_detail_delta TO sale_detail_delta_clone;
  • 克隆Delta Table分区表

    -- 新建Delta Table分区表
    CREATE TABLE IF NOT EXISTS sale_detail_delta_pt                                     
      (
        shop_name     STRING,                                                             
        customer_id   STRING,                 
        total_price   DOUBLE
      )
      PARTITIONED BY (dd STRING, hh STRING)
      TBLPROPERTIES ("table.format.version"="2");
    
    INSERT INTO sale_detail_delta_pt PARTITION (dd='01', hh='01') VALUES                
      ('s3','c3',100.3);
    
    -- 克隆示例
    CLONE TABLE sale_detail_delta_pt PARTITION (dd='01', hh='01') TO sale_detail_delta_pt_clone;  

最佳实践

实现同RegionMaxCompute项目数据迁移请参见使用CLONE TABLE实现同地域MaxCompute跨项目数据迁移