执行深层复制
深层复制将使用批量插入重新创建和重新填充表,这将自动对表进行排序。如果表具有大型未排序区域,则深层复制比 vacuum 快得多。如果您可以跟踪并发更新,我们建议您仅在深层复制操作期间进行并发更新。该过程完成后,将增量更新移到新表中。VACUUM 操作支持自动并发更新。
您可以选择四种方法之一来创建原始表的副本:
-
使用原始表 DDL。
如果 CREATE TABLE DDL 可用,那么这是最快且首选的方法。在创建新表时,您可以指定所有表和列属性,包括主键和外键。您可以使用 SHOW TABLE 函数找到原始 DDL。
-
使用 CREATE TABLE LIKE。
如果原始 DDL 不可用,您可以使用 CREATE TABLE LIKE 来重新创建原始表。新表继承父表的编码、分配键、排序键和 not-null 属性。新表不继承父表的主键和外键属性,但您可以使用 ALTER TABLE 来添加它们。
-
创建一个临时表并截断原始表。
如果您必须保留父表的主键和外键属性。如果父表有依赖关系,您可以使用 CREATE TABLE ... AS (CTAS) 以创建临时表。然后,截断原始表并从临时表填充它。
与使用永久表相比,使用临时表可极大地提高性能,但存在丢失数据的风险。在创建临时表的会话结束时将自动删除该临时表。TRUNCATE 将立即提交,即使它在事务块中。如果 TRUNCATE 成功,但会话在接下来的 INSERT 完成前关闭,则数据将丢失。如果数据丢失是不可接受的,请使用永久表。
创建表的副本后,您可能必须授予对新表的访问权限。您可以使用 GRANT 来定义访问权限。要查看和授予表的所有访问权限,您必须是以下人员之一:
-
超级用户。
-
您想复制的表的拥有者。
-
拥有 ACCESS SYSTEM TABLE 权限以查看表的权限且具有所有相关权限的授予权限的用户。
此外,您可能必须授予对于深层复制所在模式的使用权限。如果您的深层复制的模式与原始表的模式不同,也不是 public
模式,则授予使用权限是必需的。要查看和授予使用权限,您必须是以下人员之一:
-
超级用户。
-
可以授予对深层复制模式的 USAGE 权限的用户。
使用原始表 DDL 执行深层复制
-
(可选)通过运行名为
v_generate_tbl_ddl
的脚本来重新创建表 DDL。 -
使用原始 CREATE TABLE DDL 创建表的副本。
-
使用 INSERT INTO … SELECT 语句向副本填充原始表中的数据。
-
检查所授予的对于旧表的权限。您可以在 SVV_RELATION_PRIVILEGES 系统视图中查看这些权限。
-
如有必要,将旧表的权限授予新表。
-
向在原始表中具有权限的每个组和用户授予使用权限。如果您的深层复制表处于
public
模式,或者与原始表处于同一模式,则无需执行此步骤。 -
删除原始表。
-
使用 ALTER TABLE 语句将副本重命名为原始表名称。
以下示例使用名为 sample_copy 的 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 * frompublic
.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 groupgroup1
; grant INSERT, UPDATE on table sample_namespace.sample_copy to groupgroup2
; grant SELECT on table sample_namespace.sample_copy touser1
; grant INSERT, SELECT, UPDATE on table sample_namespace.sample_copy touser2
; --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 执行深层复制
-
使用 CREATE TABLE LIKE 创建新表。
-
使用 INSERT INTO … SELECT 语句将当前表中的行复制到新表。
-
检查所授予的对于旧表的权限。您可以在 SVV_RELATION_PRIVILEGES 系统视图中查看这些权限。
-
如有必要,将旧表的权限授予新表。
-
向在原始表中具有权限的每个组和用户授予使用权限。如果您的深层复制表处于
public
模式,或者与原始表处于同一模式,则无需执行此步骤。 -
删除当前表。
-
使用 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 (likepublic
.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 groupgroup1
; grant INSERT, UPDATE on table sample_namespace.sample_copy to groupgroup2
; grant SELECT on table sample_namespace.sample_copy touser1
; grant INSERT, SELECT, UPDATE on table sample_namespace.sample_copy touser2
; --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 AS 创建具有原始表中的行的临时表。
-
截断当前表。
-
使用 INSERT INTO … SELECT 语句将临时表中的行复制到原始表。
-
删除临时表。
以下示例通过创建临时表并截断原始表来对 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;