
# Iceberg表存储过程管理
在Spark中使用Iceberg前，需先配置Spark目录，spark_catalog和prod目录配置请参见[配置Iceberg Catalog](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_300767.html#mrs_01_300767)。存储过程仅在Spark 3中使用Iceberg SQL扩展时可用。
#### 使用方法
可通过**CALL**语句从任何已配置的Iceberg Catalog中调用存储过程，所有存储过程均位于system命名空间下。
**CALL**支持按名称传递参数（推荐方式）或按位置传递参数，且不支持混合使用位置参数和命名参数。
- 命名参数 所有存储过程参数都有名称。按名称传递参数时，参数顺序可以任意，且任何可选参数都可省略。
  ```
  CALL prod.system.{存储名} (arg_name_2 => 'arg_2_value', arg_name_1 => 'arg_1_value');
  ```
  
- 位置参数
  按位置传递参数时，仅当末尾的参数为可选参数时，才可省略。
  ```
  CALL prod.system.{存储名} (arg_1, arg_2, ... arg_n);
  ```
  
 
#### 快照管理
- 将表回滚到特定的快照ID版本 可使用**rollback_to_snapshot** 将表回滚到特定的快照ID。以下命令为将表**db.sample**回滚到快照ID为1的版本：
  ```
  CALL catalog_name.system.rollback_to_snapshot('db.sample', 1);
  ```
  其中，表名字段的类型为string，快照ID字段的类型为long。
  输出结果介绍请参见[表1]。
   表1回滚输出结果 
  | 参数                   | 类型   | 说明            |
  |:---|:---|:---|
  | previous_snapshot_id | long | 回滚前的当前快照ID。   |
  | current_snapshot_id  | long | 回滚后的新当前快照 ID。 |
     
  
- 将表回滚到特定时间点对应的活跃快照 可使用**rollback_to_timestamp** 将表回滚到特定时间点对应的活跃快照。以下命令为将**db.sample**表回滚到特定日期和时间：
  ```
  CALL prod.system.rollback_to_timestamp('db.sample', TIMESTAMP '2021-06-30 00:00:00.000');
  ```
  其中，表名字段的类型为string，timestamp的类型为timestamp，表示回滚目标时间戳。
  输出结果介绍请参见[表1]。
  
- 设置表的当前快照ID 可使用**set_current_snapshot**设置表的当前快照ID。与回滚不同，该操作不要求目标快照必须是表当前状态的祖先快照。例如：
  将**db.sample**表的当前快照设置为ID为1的快照：
  ```
  CALL prod.system.set_current_snapshot('db.sample', 1);
  ```
  将**db.sample**表的当前快照设置为标签s1对应的快照：
  ```
  CALL prod.system.set_current_snapshot(table => 'db.sample', ref => 's1');
  ```
  其中，表名字段的类型为string，快照ID字段的类型为long，"ref"为设置当前快照的快照引用（分支或标签），类型为string。且必须设置快照ID或ref，二者不可同时提供，也不可均不提供。
  输出结果介绍请参见[表2]。
   表2快照设置输出结果 
  | 参数                   | 类型   | 说明           |
  |:---|:---|:---|
  | previous_snapshot_id | long | 设置前的当前快照ID。  |
  | current_snapshot_id  | long | 设置后新的当前快照ID。 |
     
  
- 从指定快照中挑选变更并应用到表的当前状态 可使用**cherrypick_snapshot**从指定快照中挑选变更并应用到表的当前状态。挑选操作会基于现有快照创建一个新快照，且不会修改或删除原始快照。仅支持对追加和动态覆盖类型的快照执行挑选操作。例如：
  挑选快照1的变更：
  ```
  CALL prod.system.cherrypick_snapshot('my_table', 1);
  ```
  使用命名参数挑选快照1的变更：
  ```
  CALL prod.system.cherrypick_snapshot(snapshot_id => 1, table => 'my_table' );
  ```
  其中，"table"表示待更新的表名，类型为string；"snapshot_id"为要设为当前快照的快照ID，类型为long。
  输出结果介绍请参见[表3]。
   表3快照变更输出结果 
  | 参数                  | 类型   | 说明           |
  |:---|:---|:---|
  | source_snapshot_id  | long | 设置前的当前快照ID。  |
  | current_snapshot_id | long | 设置后新的当前快照ID。 |
     
  
- 将暂存的WAP ID中的变更发布到表的当前状态 可使用**publish_changes**将暂存的 WAP ID 中的变更发布到表的当前状态。变更发布会基于现有快照创建一个新快照，且不会修改或删除原始快照。仅追加和动态覆盖类型的快照可成功发布。例如：
  使用WAP ID "wap_id_1"发布变更：
  ```
  CALL prod.system.publish_changes('my_table', 'wap_id_1');
  ```
  使用命名参数发布变更：
  ```
  CALL prod.publish_changes(wap_id => 'wap_id_2', table => 'my_table');
  ```
  其中，"table"表示待更新的表名，类型为string；"wap_id"为要从暂存环境发布的WAP ID，类型为long。
  输出结果介绍请参见[表4]。
   表4快照变更输出结果 
  | 参数                  | 类型   | 说明           |
  |:---|:---|:---|
  | source_snapshot_id  | long | 设置前的当前快照ID。  |
  | current_snapshot_id | long | 设置后新的当前快照ID。 |
     
  
- 将一个分支的当前快照快速更新到另一个分支的最新快照 可使用**fast_forward**将一个分支的当前快照快速更新到另一个分支的最新快照。例如：
  将**main** 分支的当前快照快速更新到**audit-branch**分支的最新快照中：
  ```
  CALL prod.system.fast_forward('my_table', 'main', 'audit-branch');
  ```
  其中，表字段的类型为string，分支字段的类型为string。
  输出结果介绍请参见[表5]。
   表5快照更新输出结果 
  | 参数             | 类型     | 说明              |
  |:---|:---|:---|
  | branch_updated | string | 已完成快照快速更新的分支名称。 |
  | previous_ref   | long   | 应用快速更新前的快照ID。   |
  | updated_ref    | long   | 应用快速更新后的当前快照ID。 |
     
  
 
#### 元数据管理
在Iceberg中，每次写入、更新、删除、upsert、压缩操作都会生成新快照，同时保留旧数据和元数据，以支持快照隔离和时间旅行功能。**expire_snapshots** 可用于移除不再需要的旧快照及其文件，更多元数据管理操作请参见[Metadata management](https://iceberg.apache.org/docs/1.7.0/spark-procedures/#metadata-management)。
**expire_snapshots**会移除旧快照以及这些旧快照唯一需要的数据文件，意味着该操作绝不会移除仍被非过期快照所需要的文件。例如：
- 移除特定日期和时间之前的快照，但保留最后100个快照：
  ```
  CALL prod.system.expire_snapshots('db.sample', TIMESTAMP '2021-06-30 00:00:00.000', 100);
  ```
  
- 移除快照ID为123的快照，且此快照ID不应是当前快照：
  ```
  CALL prod.system.expire_snapshots('db.sample', snapshot_ids => array(123));
  ```
  
相关参数介绍请参见[表6]。
 表6expire_snapshots参数介绍 
| 参数                     | 类型            | 说明                                                                                                                                                                       |
|:---|:---|:---|
| table                  | string        | 需要更新的表名，必须设置。                                                                                                                                                            |
| older_than             | timestamp     | 此时间戳之前的快照将被移除，默认值为5天前。                                                                                                                                                   |
| retain_last            | int           | 保留的祖先快照数量，默认值为1，与"older_than"设置的时间戳无关。                                                                                                                                   |
| max_concurrent_deletes | int           | 用于删除文件操作的线程池大小，默认情况下，不使用线程池。                                                                                                                                             |
| stream_results         | boolean       | 当设置该参数为"true"时，删除文件将通过RDD分区发送到Spark驱动程序（默认情况下，所有文件都将发送到Spark驱动程序）。 建议将该参数设置为"true"，以防止Spark驱动程序因文件过大而发生内存溢出。 |
| snapshot_ids           | array of long | 要过期的快照ID数组。                                                                                                                                                              |
   
如果不设置**older_than** 和**retain_last** ，将使用表的过期属性，仍被分支或标签引用的快照不会被移除。默认情况下，分支和标签永不过期，但可通过表属性**history.expire.max-ref-age-ms**更改其保留策略，且主分支永不过期。
输出结果介绍请参见[表7]。
 表7expire_snapshots操作输出结果 
| 参数                                  | 类型   | 说明                  |
|:---|:---|:---|
| deleted_data_files_count            | long | 此操作删除的数据文件数量。       |
| deleted_position_delete_files_count | long | 此操作删除的**位置删除文件**数量。 |
| deleted_equality_delete_files_count | long | 此操作删除的**等值删除文件**数量。 |
| deleted_manifest_files_count        | long | 此操作删除的清单文件数量。       |
| deleted_manifest_lists_count        | long | 此操作删除的清单列表文件数量。     |
   
