【问题标题】:Copy a table (including indexes) in postgres在 postgres 中复制表(包括索引)
【发布时间】:2010-09-16 22:08:47
【问题描述】:

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

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

不幸的是 PostgreSQL 没有“创建表 .. LIKE X INCLUDING INDEXES”

【问题讨论】:

    标签: sql postgresql indexing


    【解决方案1】:

    网上有很多答案,here可以找到其中一个。

    我最终做了这样的事情:

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

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

    【讨论】:

      【解决方案2】:

      一个简单的方法是包含所有:

      CREATE TABLE new_table (LIKE original_table INCLUDING ALL);
      

      【讨论】:

      • 9.1+ 版支持这种语法。
      • 请注意,这将创建一个空表。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:
        [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 用于修复表空间问题

        【讨论】:

        • postgres 中没有“包含索引”。
        • 你用的是什么版本?阅读最新的文档,它就在那里
        • 对于 pg9.X,当使用“包含约束”(而不是“包含索引”)时,主键序列将在两个表之间共享(!)。
        • 看起来它可能需要CREATE TABLE my_table (LIKE...) 而不是CREATE TABLE my_table LIKE... 才能工作。编辑答案。
        • @PeterKrauss 你弄清楚共享主键序列的事情了吗?我正在尝试将一堆数据复制到一个新表中。我不能删除旧表并重命名新表,因为新表的 pk 指向旧表。
        【解决方案5】:

        新的 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)
        

        如果您使用的是 8.3 之前的 PostgreSQL,您可以简单地使用带有选项“-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)
        

        【讨论】:

        • 这样主键序列(x1_id_seq)将在两个表之间共享!
        • Ops,在 pg9.X 中,使用“INCLUDING CONSTRAINTS”(而不是“INCLUING INDEXES”)时,主键序列将被共享。
        【解决方案6】:

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

        我猜……

        delete from yourtable
        where <condition(s)>
        

        ...由于某种原因无法正常工作。 (愿意分享这个原因吗?)

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

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


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

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

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

        1. 您绝不会复制数据的任何部分。
        2. 当您查询每个视图/方案时,将使用已用于基表(原始“真实”表)的索引(如查询优化器所认为的那样)。无需重新定义或复制它们。
        3. 由于视图是基表中“真实”数据的“窗口”(不是快照),因此您可以在基表上添加/更新/删除并简单地重新查询视图场景,而无需随着数据随时间的变化重新创建任何内容。

        当然,需要权衡取舍。由于视图是虚拟表而不是“真实”(基本)表,因此每次访问它时实际上都在执行(可能是复杂的)查询。这可能会使事情变慢一点。但它可能不会。这取决于许多问题(数据的大小和性质、系统目录中统计信息的质量、硬件速度、使用负载等等)。在你尝试之前你不会知道。如果(且仅当)您确实发现性能慢得无法接受,那么您可能会考虑其他选项。 (物化视图、表格副本……任何以空间换时间的东西。)

        【讨论】:

        • 我已经更新了问题以解释为什么我不能从原始表中删除
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-30
        • 2011-01-25
        • 1970-01-01
        相关资源
        最近更新 更多