
# 创建Tag和Branch
本章节介绍如何创建Iceberg Tag和Branch。Tag可用于保留重要的历史快照以用于审计溯源。Branch作为可变的快照引用，可用于数据开发测试隔离、数据快速回滚修复等场景，满足数据迭代与故障恢复的需求。
如果创建Tag和Branch时没有指定RETAIN策略，Tag和Branch默认会永久保存不会自动过期。在SQL语句中，可通过**RETAIN** *\<int\>* *{DAYS \| HOURS \| MINUTES}*语法自定义保留策略。
#### 创建Tag
创建Tag的操作如下
- 每周保留1个快照，持续1个周。
  1. 获取current-snapshot-id：
     ```
     DESCRIBE EXTENDED prod.db.table;
     ```
     其中，创建"local.db.table"详细操作请参见[从零开始使用Iceberg](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_300910.html#mrs_01_300910)。
     例如，获取到的current-snapshot-id为"2767263131158701491"。
     
  
  2. 可以通过每周标记快照并将Tag保留期设置为一个周来实现。
     ```
     ALTER TABLE prod.db.table CREATE TAG EOM_01 AS OF VERSION {current-snapshot-id} RETAIN 7 DAYS;
     ```
     例如，{current-snapshot-id}为"2767263131158701491"，则执行以下命令：
     ```
     ALTER TABLE prod.db.table CREATE TAG EOM_01 AS OF VERSION 2767263131158701491 RETAIN 7 DAYS;
     ```
     
   
 
- 每月保留1个快照，持续6个月。
  可以通过每月标记快照并将Tag保留期设置为6个月来实现：
  ```
  ALTER TABLE prod.db.table CREATE TAG EOM_01 AS OF VERSION {current-snapshot-id} RETAIN 180 DAYS;
  ```
  
- 每年保留1个快照，永久保存。
  可以通过标记年度快照来实现。Branch和Tag的默认保留期不设置时默认永久。
  ```
  ALTER TABLE prod.db.table CREATE TAG EOY_2026 AS OF VERSION {current-snapshot-id};
  ```
  
#### 创建Branch
创建Branch的流程如下：
1. 首先设置"write.wap.enabled"为"true"以开启写前预提交功能：
   ```
   ALTER TABLE prod.db.table SET TBLPROPERTIES ( 'write.wap.enabled'='true');
   ```
   
2. 基于主表创建分支。
   例如，基于快照snapshot-id创建分支**audit_branch** ，该分支将被写入并保留1周：
   ```
   ALTER TABLE prod.db.table CREATE BRANCH audit_branch AS OF VERSION {snapshot-id} RETAIN 7 DAYS;
   ```
   
3. 切换分支并执行写入操作。 通过切换**audit_branch**分支去验证表功能或者数据质量等，不影响表的主分支。
   切换分支：
   ```
   SET spark.wap.branch = audit_branch;
   ```
   写入数据：
   ```
   INSERT INTO prod.db.table VALUES (5, 'e');
   ```
   查看表数据：
   ```
   select * from prod.db.table;
   ```
   查看的表数据中包含新写入的数据。
   
4. 验证通过后，可将主分支推进至**audit_branch** 分支的最新状态，以更新主表状态：
   ```
   CALL prod.system.fast_forward('db.table', 'main', 'audit_branch');
   ```
   
5. 1周后执行expireSnapshots操作，该过期分支将被删除。
**注意：**主表执行schema evolution对所有分支都生效。操作如下所示：
1. 创建表并插入数据。 
   1. 创建表：
      ```
      CREATE TABLE prod.db.table (id bigint, data string, col float);
      ```
      
   
   2. 向表中插入数据：
      ```
      INSERT INTO prod.db.table VALUES (1, 'a', 1.0), (2, 'b', 2.0), (3, 'c', 3.0);
      ```
      
   
   3. 查询表数据：
      ```
      SELECT * FROM prod.db.table;
      ```
      例如，查询结果为：
      ```
      -- 1   a   1.0 
      -- 2   b   2.0 
      -- 3   c   3.0
      ```
      
   
   
   
   
2. 创建分支指向当前快照： 
   ```
   ALTER TABLE prod.db.table CREATE BRANCH test_branch;
   ```
   查询分支数据：
   ```
   SELECT * FROM prod.db.table VERSION AS OF 'test_branch';
   ```
   例如，查询结果为：
   ```
   -- 1   a   1.0 
   -- 2   b   2.0 
   -- 3   c   3.0
   ```
   
   
3. 修改Schema，删除"col"列并添加一个名为"new_col"的新列。 
   1. 删除"col"列：
      ```
      ALTER TABLE prod.db.table DROP COLUMN col;
      ```
      
   
   2. 添加一个名为"new_col"的新列：
      ```
      ALTER TABLE prod.db.table ADD COLUMN new_col date;
      ```
      
   
   3. 向表中插入数据：
      ```
      INSERT INTO prod.db.table VALUES (4, 'd', date('2024-04-04')), (5, 'e', date('2024-05-05'));
      ```
      
   
   4. 查询表数据：
      ```
      SELECT * FROM prod.db.table;
      ```
      例如，查询结果为：
      ```
      -- 1   a   NULL 
      -- 2   b   NULL 
      -- 3   c   NULL 
      -- 4   d   2024-04-04 
      -- 5   e   2024-05-05
      ```
      
   
   
   
   
4. 查询分支快照： 
   - 方式一：
     ```
     SELECT * FROM prod.db.table.branch_test_branch;
     ```
     
   
   - 方式二：
     ```
     SELECT * FROM prod.db.table VERSION AS OF 'test_branch';
     ```
     
   
   
   例如，查询结果为：
   ```
   -- 1   a   NULL 
   -- 2   b   NULL 
   -- 3   c   NULL
   ```
   
   
5. 向分支中写入数据，需要使用主表最新的Schema： 
   ```
   INSERT INTO prod.db.table.branch_test_branch VALUES (6, 'e', date('2024-06-06')), (7, 'g', date('2024-07-07'));
   ```
   查询分支数据：
   ```
   SELECT * FROM prod.db.table VERSION AS OF 'test_branch';
   ```
   例如，查询结果为：
   ```
   -- 6   e   2024-06-06 
   -- 7   g   2024-07-07 
   -- 1   a   NULL 
   -- 2   b   NULL 
   -- 3   c   NULL
   ```
   
   
 
