postgresでテーブル(インデックスを含む)をコピーする


85

postgresテーブルがあります。そこからいくつかのデータを削除する必要があります。一時テーブルを作成し、データをコピーして、インデックスを再作成し、必要な行を削除しました。この元のテーブルがデータのソースであるため、元のテーブルからデータを削除できません。Xの削除に依存する結果を取得する必要がある場合もあれば、Yを削除する必要がある場合もあります。したがって、すべての元のデータが常に存在し、利用可能である必要があります。

ただし、テーブルを再作成して再度コピーし、インデックスを再作成するのは少しばかげているようです。とにかくpostgresに「構造、データ、インデックスを含むこのテーブルの完全な個別のコピーが欲しい」と言うことはありますか?

残念ながら、PostgreSQLには「CREATETABLE .. LIKE X INCLUDINGINDEXES」がありません。

回答:


108

新しいPostgreSQL(ドキュメントによると8.3以降)は「INCLUDINGINDEXES」を使用できます。

# 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)

PostgreSQL 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)

14
このようにして、主キーシーケンス(x1_id_seq)が2つのテーブル間で共有されます!
Jauzsika 2011

2
Ops、pg9.Xでは、「INCLUDING CONSTRAINTS」(「INCLUING INDEXES」ではない)を使用すると、主キーシーケンスが共有されます。
ピータークラウス2012年

44
[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]  

これが例です

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

最初から新しいテーブルを作成するもう1つの方法は、

    CREATE TABLE films_recent (LIKE films INCLUDING INDEXES);  

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

2番目の方法を使用した場合、Postgresqlにはテーブルスペースの問題を修正するためのパッチがあります。


postgresには「INCLUDINGINDEXES」はありません。
ロリー

2
どのバージョンを使用していますか?最新のドキュメントを読んでください、それはそこにあります
WolfmanDragon 2008年

6
pg9.Xでは、「INCLUDING CONSTRAINTS」(「INCLUING INDEXES」ではない)を使用すると、主キーシーケンスが2つのテーブル間で共有されます(!)。
ピータークラウス2012年

動作するためCREATE TABLE my_table (LIKE...)にでCREATE TABLE my_table LIKE...はなく、必要になる可能性があるようです。編集された回答。
Jason Swett 2013

@PeterKraussは、共有された主キーシーケンスのことを理解しましたか?大量のデータを新しいテーブルにコピーしようとしています。新しいテーブルのpkが古いテーブルを指しているため、古いテーブルを削除して新しいテーブルの名前を変更することはできません。
yellottyellott 2015

4

postgresテーブルがあります。そこからいくつかのデータを削除する必要があります。

私はそれを推測します...

delete from yourtable
where <condition(s)>

...何らかの理由で機能しません。(その理由を共有する気ですか?)

一時テーブルを作成し、データをコピーして、インデックスを再作成し、必要な行を削除しました。

pg_dumpとpg_restoreを調べてください。いくつかの巧妙なオプションでpg_dumpを使用し、おそらくpg_restoringの前に出力を編集するとうまくいくかもしれません。


データに対して「whatif」タイプの分析を行っているので、ビューを使用したほうがよいのではないかと思います。

除外するものの否定に基づいて、テストするシナリオごとにビューを定義できます。つまり、含めたいものに基づいてビューを定義します。たとえば、X = Yの行を「削除」したデータに「ウィンドウ」が必要な場合は、(X!= Y)の行としてビューを作成します。

ビューは、定義クエリとしてデータベース(システムカタログ)に保存されます。ビューをクエリするたびに、データベースサーバーは、ビューを定義する基になるクエリを検索し、それを実行します(また、使用した他の条件と組み合わせて)。このアプローチにはいくつかの利点があります。

  1. データのいかなる部分も複製することはありません。
  2. 各ビュー/シナリオをクエリするときに、ベーステーブル(元の「実際の」テーブル)にすでに使用されているインデックスが使用されます(クエリオプティマイザーによって適切と見なされます)。それらを再定義またはコピーする必要はありません。
  3. ビューはベーステーブルの「実際の」データの「ウィンドウ」(シェイプショットではない)であるため、ベーステーブルで追加/更新/削除し、ビューシナリオを再クエリするだけで、次のように何も再作成する必要はありません。データは時間とともに変化します。

もちろん、トレードオフがあります。ビューは仮想テーブルであり、「実際の」(ベース)テーブルではないため、実際には、ビューにアクセスするたびに(おそらく複雑な)クエリを実行しています。これは物事を少し遅くするかもしれません。しかし、そうではないかもしれません。それは多くの問題(データのサイズと性質、システムカタログの統計の品質、ハードウェアの速度、使用負荷など)に依存します。試してみるまでわかりません。パフォーマンスが許容できないほど遅いことが実際にわかった場合(そしてその場合のみ)、他のオプションを検討する可能性があります。(マテリアライズドビュー、テーブルのコピー、...スペースを時間と交換するもの。)


元のテーブルから削除できない理由を説明するために質問を更新しました
Rory

4

ウェブ上には多くの答えがありますが、そのうちの1つはここにあります

私は次のようなことをすることになりました:

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

これにより、スキーマとインデックスを含むデータがコピーされますが、トリガーと制約は含まれません。インデックスは元のテーブルと共有されるため、いずれかのテーブルに新しい行を追加すると、カウンターが増加することに注意してください。


1

selectを使用して新しいテーブルを作成し、必要なデータを取得します。次に、古いテーブルを新しいテーブルと交換します。

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

0

簡単な方法は、すべてを含めることです。

CREATE TABLE new_table (LIKE original_table INCLUDING ALL);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.