

 从补丁 198 开始，Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息，请参阅[博客文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

# 执行深层复制
<a name="performing-a-deep-copy"></a>

深层复制将使用批量插入重新创建和重新填充表，这将自动对表进行排序。如果表具有大型未排序区域，则深层复制比 vacuum 快得多。如果您可以跟踪并发更新，我们建议您仅在深层复制操作期间进行并发更新。该过程完成后，将增量更新移到新表中。VACUUM 操作支持自动并发更新。

您可以选择四种方法之一来创建原始表的副本：
+ 使用原始表 DDL。

  如果 CREATE TABLE DDL 可用，那么这是最快且首选的方法。在创建新表时，您可以指定所有表和列属性，包括主键和外键。您可以使用 SHOW TABLE 函数找到原始 DDL。
+ 使用 CREATE TABLE LIKE。

  如果原始 DDL 不可用，您可以使用 CREATE TABLE LIKE 来重新创建原始表。新表继承父表的编码、分配键、排序键和 not-null 属性。新表不继承父表的主键和外键属性，但您可以使用 [ALTER TABLE](r_ALTER_TABLE.md) 来添加它们。
+ 创建一个临时表并截断原始表。

  如果您必须保留父表的主键和外键属性。如果父表有依赖关系，您可以使用 CREATE TABLE ... AS (CTAS) 以创建临时表。然后，截断原始表并从临时表填充它。

  与使用永久表相比，使用临时表可极大地提高性能，但存在丢失数据的风险。在创建临时表的会话结束时将自动删除该临时表。TRUNCATE 将立即提交，即使它在事务块中。如果 TRUNCATE 成功，但会话在接下来的 INSERT 完成前关闭，则数据将丢失。如果数据丢失是不可接受的，请使用永久表。

创建表的副本后，您可能必须授予对新表的访问权限。您可以使用 [GRANT](r_GRANT.md) 来定义访问权限。要查看和授予表的所有访问权限，您必须是以下人员之一：
+  超级用户。
+  您想复制的表的拥有者。
+  拥有 ACCESS SYSTEM TABLE 权限以查看表的权限且具有所有相关权限的授予权限的用户。

此外，您可能必须授予对于深层复制所在模式的使用权限。如果您的深层复制的模式与原始表的模式不同，也不是 `public` 模式，则授予使用权限是必需的。要查看和授予使用权限，您必须是以下人员之一：
+  超级用户。
+  可以授予对深层复制模式的 USAGE 权限的用户。

**使用原始表 DDL 执行深层复制**

1. （可选）通过运行名为 `v_generate_tbl_ddl` 的脚本来重新创建表 DDL。

1. 使用原始 CREATE TABLE DDL 创建表的副本。

1. 使用 INSERT INTO … SELECT 语句向副本填充原始表中的数据。

1. 检查所授予的对于旧表的权限。您可以在 SVV\$1RELATION\$1PRIVILEGES 系统视图中查看这些权限。

1. 如有必要，将旧表的权限授予新表。

1. 向在原始表中具有权限的每个组和用户授予使用权限。如果您的深层复制表处于 `public` 模式，或者与原始表处于同一模式，则无需执行此步骤。

1. 删除原始表。

1. 使用 ALTER TABLE 语句将副本重命名为原始表名称。

以下示例使用名为 sample\$1copy 的 SAMPLE 的副本对 SAMPLE 表执行深层复制。

```
--Create a copy of the original table in the sample_namespace namespace using the original CREATE TABLE DDL.
create table sample_namespace.sample_copy ( … );

--Populate the copy with data from the original table in the public namespace.
insert into sample_namespace.sample_copy (select * from public.sample);

--Check SVV_RELATION_PRIVILEGES for the original table's privileges.
select * from svv_relation_privileges where namespace_name = 'public' and relation_name = 'sample' order by identity_type, identity_id, privilege_type;

--Grant the original table's privileges to the copy table.
grant DELETE on table sample_namespace.sample_copy to group group1;
grant INSERT, UPDATE on table sample_namespace.sample_copy to group group2;
grant SELECT on table sample_namespace.sample_copy to user1;
grant INSERT, SELECT, UPDATE on table sample_namespace.sample_copy to user2;
         
--Grant usage permission to every group and user that has privileges in the original table.
grant USAGE on schema sample_namespace to group group1, group group2, user1, user2;

--Drop the original table.
drop table public.sample;

--Rename the copy table to match the original table's name.
alter table sample_namespace.sample_copy rename to sample;
```

**使用 CREATE TABLE LIKE 执行深层复制**

1. 使用 CREATE TABLE LIKE 创建新表。

1. 使用 INSERT INTO … SELECT 语句将当前表中的行复制到新表。

1. 检查所授予的对于旧表的权限。您可以在 SVV\$1RELATION\$1PRIVILEGES 系统视图中查看这些权限。

1. 如有必要，将旧表的权限授予新表。

1. 向在原始表中具有权限的每个组和用户授予使用权限。如果您的深层复制表处于 `public` 模式，或者与原始表处于同一模式，则无需执行此步骤。

1. 删除当前表。

1. 使用 ALTER TABLE 语句将新表重命名为原始表名称。

以下示例使用 CREATE TABLE LIKE 对 SAMPLE 表执行深层复制。

```
--Create a copy of the original table in the sample_namespace namespace using CREATE TABLE LIKE.
create table sameple_namespace.sample_copy (like public.sample);

--Populate the copy with data from the original table.
insert into sample_namespace.sample_copy (select * from public.sample);

--Check SVV_RELATION_PRIVILEGES for the original table's privileges.
select * from svv_relation_privileges where namespace_name = 'public' and relation_name = 'sample' order by identity_type, identity_id, privilege_type;

--Grant the original table's privileges to the copy table.
grant DELETE on table sample_namespace.sample_copy to group group1;
grant INSERT, UPDATE on table sample_namespace.sample_copy to group group2;
grant SELECT on table sample_namespace.sample_copy to user1;
grant INSERT, SELECT, UPDATE on table sample_namespace.sample_copy to user2;
         
--Grant usage permission to every group and user that has privileges in the original table.
grant USAGE on schema sample_namespace to group group1, group group2, user1, user2;

--Drop the original table.
drop table public.sample;

--Rename the copy table to match the original table's name.
alter table sample_namespace.sample_copy rename to sample;
```

**通过创建临时表并截断原始表来执行深层复制**

1. 使用 CREATE TABLE AS 创建具有原始表中的行的临时表。

1. 截断当前表。

1. 使用 INSERT INTO … SELECT 语句将临时表中的行复制到原始表。

1. 删除临时表。

以下示例通过创建临时表并截断原始表来对 SALES 表执行深层复制。由于原始表仍然存在，因此您无需授予对副本表的权限。

```
--Create a temp table copy using CREATE TABLE AS.
create temp table salestemp as select * from sales;

--Truncate the original table.
truncate sales;

--Copy the rows from the temporary table to the original table.
insert into sales (select * from salestemp);

--Drop the temporary table.
drop table salestemp;
```