2008-10-13 6 views
72

Ich habe eine Postgres-Tabelle. Ich muss einige Daten davon löschen. Ich wollte eine temporäre Tabelle erstellen, die Daten kopieren, die Indizes neu erstellen und die Zeilen löschen, die ich brauche. Ich kann keine Daten aus der Originaltabelle löschen, da diese Originaltabelle die Datenquelle ist. In einem Fall muss ich einige Ergebnisse erhalten, die davon abhängen, X zu löschen, in einem anderen Fall muss ich Y löschen. Also brauche ich alle Originaldaten, die immer verfügbar und verfügbar sind.Kopieren Sie eine Tabelle (einschließlich Indizes) in Postgres

Es scheint jedoch ein wenig albern, die Tabelle neu zu erstellen und es erneut zu kopieren und die Indizes neu zu erstellen. Gibt es in Postgres überhaupt, es zu sagen "Ich möchte eine vollständige separate Kopie dieser Tabelle, einschließlich Struktur, Daten und Indizes"?

Leider hat PostgreSQL haben nicht ein „CREATE TABLE .. LIKE X einschließlich Indizes‘

Antwort

1

Erstellen Sie eine neue Tabelle, die eine Auswahl mit der Daten greifen Sie wollen. Dann mit dem neuen die alte Tabelle tauschen.

create table mynewone as select * from myoldone where ... 
mess (re-create) with indexes after the table swap. 
37
[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] 

Hier ist ein example

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

Der andere Weg eine neue Tabelle aus dem ersten zu erstellen ist

CREATE TABLE films_recent (LIKE films INCLUDING INDEXES); 

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

Hinweis zu verwenden, dass Postgresql einen patch aus Tabellen Probleme zu beheben hat, wenn die zweite Methode

+0

In Postgres gibt es kein "INCLUSIVE INDEXES". – Rory

+2

Welche Version verwenden Sie? Lesen Sie das neueste Dokument, es ist dort – WolfmanDragon

+6

mit pg9.X, wenn "INCLUDING CONSTRAINTS" (nicht "INCLUING INDEXES") verwendet wird, wird die Primärschlüsselsequenz zwischen den beiden Tabellen (!) Geteilt. –

4

ich einen Postgres Tisch verwendet wird. Ich muss einige Daten löschen.

Ich nehme an, dass ...

delete from yourtable 
where <condition(s)> 

... wird aus irgendeinem Grund nicht funktionieren. (Pflege, den Grund teilen?)

ich eine temporäre Tabelle erstellen würde, kopieren Sie die Daten in, erstellen Sie die Indizes und die Löschen Sie die Zeilen I Notwendigkeit.

Schauen Sie in pg_dump und pg_restore. Die Verwendung von pg_dump mit einigen cleveren Optionen und vielleicht die Bearbeitung der Ausgabe vor pg_restoring könnte den Trick machen.

Da Sie "was wäre wenn" -Typ Analyse auf die Daten, frage ich mich, ob Sie besser mit Ansichten sein könnten.

Sie können für jedes Szenario, das Sie testen möchten, eine Sicht definieren, die auf der Negation des auszuschließenden Objekts basiert. Das heißt, Sie definieren eine Sicht basierend auf dem, was Sie INkludieren möchten. Wenn Sie beispielsweise ein "Fenster" für die Daten wünschen, in denen Sie die Zeilen mit X = Y "gelöscht" haben, würden Sie eine Ansicht als Zeilen mit (X! = Y) erstellen.

Ansichten werden in der Datenbank (im Systemkatalog) als definierende Abfrage gespeichert. Jedes Mal, wenn Sie die Ansicht abfragen, sucht der Datenbankserver die zugrunde liegende Abfrage, die ihn definiert und ausführt (UND mit anderen von Ihnen verwendeten Bedingungen UND-verknüpft).Dieser Ansatz bietet mehrere Vorteile:

  1. Sie kopieren niemals einen Teil Ihrer Daten.
  2. Die Indizes, die bereits für die Basistabelle (Ihre ursprüngliche, "echte" Tabelle) verwendet werden, werden beim Abfragen jeder Ansicht/jedes Szenarios (wie vom Abfrageoptimierer erkannt) verwendet. Sie brauchen sie nicht neu zu definieren oder zu kopieren.
  3. Da eine Ansicht ein "Fenster" (NICHT ein Shapshot) für die "echten" Daten in der Basistabelle ist, können Sie in Ihrer Basistabelle hinzufügen/aktualisieren/löschen und die Ansichtsszenarien einfach erneut abfragen Erstellen Sie alles neu, während sich die Daten im Laufe der Zeit ändern.

Es gibt natürlich einen Kompromiss. Da eine Ansicht eine virtuelle Tabelle und keine "echte" (Basis-) Tabelle ist, führen Sie bei jedem Zugriff eine (möglicherweise komplexe) Abfrage aus. Dies kann die Dinge etwas verlangsamen. Aber vielleicht nicht. Dies hängt von vielen Faktoren ab (Größe und Art der Daten, Qualität der Statistiken im Systemkatalog, Geschwindigkeit der Hardware, Auslastung und vieles mehr). Du wirst es nicht wissen, bis du es versuchst. Wenn (und nur wenn) Sie tatsächlich feststellen, dass die Leistung inakzeptabel langsam ist, dann können Sie sich andere Optionen ansehen. (Materialisierten Ansichten, Kopien von Tabellen, ... alles, was Raum für Zeit handelt.)

+0

Ich habe die Frage aktualisiert, um zu erklären, warum ich nicht einfach aus der ursprünglichen Tabelle – Rory

+0

löschen kann Ich habe die Antwort basierend auf Ihrer weiteren Eingabe aktualisiert. – Alan

89

New PostgreSQL (seit 8.3 nach docs) verwenden können, "einschließlich Indizes":

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

Wie Sie sehen können Ich teste am 8.3. Jetzt

, lassen Sie uns erstellen Tabelle:

# 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 

Und sehen, wie es aussieht:

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

Jetzt können wir die Struktur kopieren:

# 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 

Und die Struktur überprüfen:

Wenn Sie PostgreSQL verwenden pre-8.3, können Sie einfach mit der Option "-t" verwenden pg_dump 1 Tabelle angeben, Namensänderung Tabelle in dump, und es wieder laden:

=> 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 

Und nun die Tabelle ist:

# \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) 
+0

+1 Eine großartige Antwort. –

+13

Auf diese Weise wird die Primärschlüsselfolge (x1_id_seq) zwischen den beiden Tabellen geteilt! – Jauzsika

+2

Ops, mit PG9.X, die Primärschlüssel-Sequenz wird geteilt, wenn "INCLUDING CONSTRAINTS" (nicht "INCLUING INDEXES") verwendet wird. –