简介
关系数据库中从一个表到另一个表的数据复制(Clone) 是将数据从现有表复制到同一数据库中新的或现存的表定义的常用流程。可以出于各种原因执行此过程,比如数据备份、信息复制和测试,以及其他目的。Postgres和其他第三方工具提供了几种将数据从一个表复制到另一个表的技术。
本文的目的是试图找到在Postgres中克隆数据的最快方法,以便为将来这种类型的请求做好准备。为此,将展示几个示例及其结果。
为了便于示例,将使用以下表定义,为了简化测试活动,表将不具有索引或触发器:
postgres=# CREATE TABLE origin_table (i bigint, d date, j int, t character varying (10));
CREATE TABLE
postgres=# INSERT INTO origin_table SELECT i,'2024-02-15', i/10, md5(i::text)::character varying(10) FROM generate_series(1,20000000) as i;
INSERT 0 20000000
postgres=# ANALYZE origin_table ;
ANALYZE
postgres=# CREATE TABLE target_table (i bigint, d date, j int, t character varying (10));
CREATE TABLE
测试
INSERT INTO SELECT (IIS)
使用几乎标准的SQL克隆数据的最常见方法之一。IIS语句用于从源表中select数据,然后将其insert到目标表中。
postgres=# INSERT INTO target_table SELECT * FROM origin_table ;
INSERT 0 20000000
Duración: 12795,623 ms (00:12,796)
--query plan
postgres=# EXPLAIN (ANALYZE,VERBOSE) INSERT INTO target_table SELECT * FROM origin_table ;
QUERY PLAN
------------------------------------------------------------------------------------
Insert on public.target_table (cost=0.00..347059.24 rows=0 width=0) (actual time=12757.949..12767.355 rows=0 loops=1)
-> Seq Scan on public.origin_table (cost=0.00..347059.00 rows=20000000 width=27) (actual time=0.026..2271.678 rows=20000000 loops=1)
Output: origin_table.i, origin_table.d, origin_table.j, origin_table.t
Planning Time: 2.000 ms
Execution Time: 12779.611 ms
(5 filas)
如EXPLAIN命令所示,IIS在查询计划中生成两种类型的节点:INSERT和SEQSCAN。
如果目标表使用的是unlogged,情况又会怎样呢? 它允许您绕过WAL并对表执行快速写操作,尽管它有一些缺点(没有持久性、没有复制),但值得测试一下,看看它是否有助于加快克隆过程。在克隆过程结束时转到日志表将使该数据持久且可复制,但是,这个过程需要多长时间?
postgres=# TRUNCATE target_table ;
TRUNCATE TABLE
postgres=# ALTER TABLE target_table SET UNLOGGED ;
ALTER TABLE
postgres=# \timing
El despliegue de duración está activado.
postgres=# INSERT INTO target_table SELECT * FROM origin_table ;
INSERT 0 20000000
Duración: 6498,045 ms (00:06,498)
postgres=# ALTER TABLE target_table SET LOGGED ;
ALTER TABLE
Duración: 7723,691 ms (00:07,724)
从UNLOGGED表更改为LOGGED表似乎代价高昂,而且并不代表数据表克隆过程的改进。整个过程(INSERT到unlogged的表+ SET表为logged)花费14.2秒。
CREATE TABLE AS (CTAS)
该命令符合SQL标准,创建一个新表,并在一个命令中使用查询结果中的数据填充该表。CTAS也是克隆所有数据库中数据的最常用方法之一。请记住,如果您有约束、索引或触发器,这些组件将不会被复制。