web-dev-qa-db-ja.com

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

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

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

残念ながら、PostgreSQLには「CREATE TABLE .. LIKE X INCLUDING INDEXES」がありません

80
Rory

新しい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)
102
user80168
[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';

最初から新しいテーブルを作成する他の方法は、使用することです

    CREATE TABLE films_recent (LIKE films INCLUDING INDEXES);  

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

2番目の方法が使用されている場合、Postgresqlには patch outがあり、テーブルスペースの問題を修正することに注意してください。

42
WolfmanDragon

Postgresテーブルがあります。データを削除する必要があります。

私は...

delete from yourtable
where <condition(s)>

...何らかの理由で動作しません。 (その理由を共有しますか?)

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

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


データに対して「what if」タイプの分析を行っているため、ビューを使用する方が良いのではないかと考えています。

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

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

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

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

4
Alan

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

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

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

CREATE TABLE new_table (LIKE original_table INCLUDING ALL);
0
Ringtail