复制postgres中的表(包括索引)

时间:2008-10-13 16:14:09

标签: sql postgresql indexing

我有一张postgres表。我需要从中删除一些数据。我打算创建一个临时表,复制数据,重新创建索引并删除我需要的行。我无法从原始表中删除数据,因为此原始表是数据源。在一种情况下,我需要得到一些取决于删除X的结果,在另一种情况下,我需要删除Y.所以我需要所有原始数据始终存在并可用。

然而,重新创建表并再次复制并重新创建索引似乎有点愚蠢。无论如何在postgres中告诉它“我想要一个完整的表格副本,包括结构,数据和索引”?

不幸的是,PostgreSQL没有“创建表..像X包含索引'

7 个答案:

答案 0 :(得分:100)

新PostgreSQL(根据文档自8.3起)可以使用“包含索引”:

# select version();
                                             version
-------------------------------------------------------------------------------------------------
 PostgreSQL 8.3.7 on x86_64-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)
(1 row)

正如您所看到的,我正在测试8.3。

现在,让我们创建表:

# create table x1 (id serial primary key, x text unique);
NOTICE:  CREATE TABLE will create implicit sequence "x1_id_seq" for serial column "x1.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "x1_pkey" for table "x1"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "x1_x_key" for table "x1"
CREATE TABLE

看看它的样子:

# \d x1
                         Table "public.x1"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x1_pkey" PRIMARY KEY, btree (id)
    "x1_x_key" UNIQUE, btree (x)

现在我们可以复制结构:

# create table x2 ( like x1 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES );
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "x2_pkey" for table "x2"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "x2_x_key" for table "x2"
CREATE TABLE

检查结构:

# \d x2
                         Table "public.x2"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x2_pkey" PRIMARY KEY, btree (id)
    "x2_x_key" UNIQUE, btree (x)

如果你使用的是pregreSQL 8.3之前的版本,你只需使用带有选项“-t”的pg_dump来指定1个表,在转储中更改表名,然后重新加载它:

=> pg_dump -t x2 | sed 's/x2/x3/g' | psql
SET
SET
SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE

现在表格是:

# \d x3
                         Table "public.x3"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x3_pkey" PRIMARY KEY, btree (id)
    "x3_x_key" UNIQUE, btree (x)

答案 1 :(得分:42)

[CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name
    [ (column_name [, ...] ) ]
    [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
    [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
    [ TABLESPACE tablespace ]
    AS query][1]  

这是example

CREATE TABLE films_recent AS
  SELECT * FROM films WHERE date_prod >= '2002-01-01';

从第一个创建新表的另一种方法是使用

    CREATE TABLE films_recent (LIKE films INCLUDING INDEXES);  

    INSERT INTO films_recent
         SELECT *
           FROM books
          WHERE date_prod >= '2002-01-01';  

请注意,如果使用第二种方法,Postgresql有patch来修复表空间问题

答案 2 :(得分:4)

  

我有一张postgres表。我需要   从中删除一些数据。

我认为......

delete from yourtable
where <condition(s)>

......由于某种原因不会起作用。 (小心分享这个理由?)

  

我打算创建一个临时的   表,复制数据,重新创建   索引和删除行我   需要。

查看pg_dump和pg_restore。使用pg_dump和一些聪明的选项,也许在pg_restoring之前编辑输出可能会有效。


由于您正在对数据进行“假设”类型分析,我想知道您是否可以更好地使用视图。

您可以根据要排除的内容的否定,为要测试的每个方案定义视图。即,根据您想要包含的内容定义视图。例如,如果你想要“删除”X = Y的行的数据的“窗口”,那么你将创建一个视图为行(X!= Y)。

视图作为定义查询存储在数据库中(在系统目录中)。每次查询视图时,数据库服务器都会查找定义它的基础查询并执行该查询(与您使用的任何其他条件进行AND运算)。这种方法有几个好处:

  1. 您永远不会复制数据的任何部分。
  2. 当您查询每个视图/场景时,将使用已用于基表的索引(您的原始“真实”表)(如查询优化器所示)。无需重新定义或复制它们。
  3. 由于视图是基表中“真实”数据的“窗口”(不是shapshot),您可以在基表上添加/更新/删除,只需重新查询视图场景而无需随着数据的变化,随着时间的推移重新创建任何内容。
  4. 当然,需要权衡利弊。由于视图是虚拟表而不是“真实”(基础)表,因此每次访问时,您实际上都在执行(可能是复杂的)查询。这可能会使事情变慢。但它可能不会。这取决于许多问题(数据的大小和性质,系统目录中的统计数据质量,硬件速度,使用负载等等)。在你尝试之前你不会知道。如果(并且仅当)您实际发现性能慢得令人无法接受,那么您可能会考虑其他选项。 (物化视图,表格副本,......随时间交换空间的任何东西。)

答案 3 :(得分:1)

使用select创建一个新表来获取所需的数据。然后将旧表与新表交换。

create table mynewone as select * from myoldone where ...
mess (re-create) with indexes after the table swap.

答案 4 :(得分:1)

网络上有很多答案,here就是其中之一。

我最终做了这样的事情:

create table NEW ( like ORIGINAL including all);
insert into NEW select * from ORIGINAL

这将复制模式和包括索引的数据,但不包括触发器和约束。 请注意,索引与原始表共享,因此当向其中一个表添加新行时,计数器将递增。

另请参见答案here

答案 5 :(得分:0)

一种简单的方法是包括全部:

CREATE TABLE new_table (LIKE original_table INCLUDING ALL);

答案 6 :(得分:0)

网络上有很多答案,here就是其中之一。

我最终做了这样的事情:

create table NEW ( like ORIGINAL including all);
insert into NEW select * from ORIGINAL

这将复制模式和包括索引的数据,但不包括触发器和约束。 请注意,索引与原始表共享,因此当向其中一个表添加新行时,计数器将递增。