2008-10-13 19 views
72

J'ai une table postgres. J'ai besoin d'effacer certaines données. J'allais créer une table temporaire, copier les données, recréer les index et supprimer les lignes dont j'avais besoin. Je ne peux pas supprimer les données de la table d'origine, car cette table d'origine est la source des données. Dans un cas, je dois obtenir des résultats qui dépendent de la suppression de X, dans un autre cas, je vais devoir supprimer Y. J'ai donc besoin de toutes les données d'origine pour être toujours disponible.Copier une table (y compris les index) dans postgres

Cependant, il semble un peu stupide de recréer la table et de la recopier et de recréer les index. Y at-il de toute façon dans postgres pour le dire "Je veux une copie séparée complète de cette table, y compris la structure, les données et les index"?

Malheureusement PostgreSQL ne dispose pas d'un « CREATE TABLE .. COMME X, Y COMPRIS LES INDICES »

Répondre

1

Créer une nouvelle table à l'aide d'une sélection pour saisir les données que vous voulez. Ensuite, échanger l'ancienne table avec le nouveau.

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] 

Voici un example

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

L'autre façon pour créer une nouvelle table à partir de la première consiste à utiliser

CREATE TABLE films_recent (LIKE films INCLUDING INDEXES); 

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

Notez que Postgresql a un patch sur pour résoudre les problèmes de tablespace si la deuxième méthode est utilisée

+0

Il n'y a pas "INCLUDING INDEXES" dans postgres. – Rory

+2

Quelle version utilisez-vous? Lisez le dernier document, il est là – WolfmanDragon

+6

avec pg9.X, en utilisant "INCLUDING CONSTRAINTS" (pas "INCLUANT INDEXES") la séquence de clé primaire sera partagée entre les deux tables (!). –

4

J'ai une table postgres. J'ai besoin de pour supprimer des données.

Je suppose que ...

delete from yourtable 
where <condition(s)> 

... ne fonctionnera pas pour une raison quelconque. (Soins à partager cette raison?)

j'allais créer une table temporaire , copier les données, recréer les index et supprimer les lignes que je besoin.

Regardez dans pg_dump et pg_restore. Utiliser pg_dump avec des options intelligentes et peut-être éditer la sortie avant que pg_restoring ne fasse l'affaire. Puisque vous faites une analyse de type "what if" sur les données, je me demande si vous feriez mieux d'utiliser les vues.

Vous pouvez définir une vue pour chaque scénario que vous souhaitez tester en fonction de la négation de ce que vous souhaitez exclure. C'est-à-dire, définissez une vue basée sur ce que vous voulez inclure. Par exemple, si vous voulez une "fenêtre" sur les données où vous avez "supprimé" les lignes où X = Y, alors vous créerez une vue comme des lignes où (X! = Y). Les vues sont stockées dans la base de données (dans le catalogue système) en tant que requête de définition. Chaque fois que vous interrogez la vue, le serveur de base de données recherche la requête sous-jacente qui la définit et l'exécute (avec les autres conditions que vous avez utilisées).Cette approche présente plusieurs avantages:

  1. Vous ne dupliquez jamais aucune partie de vos données.
  2. Les index déjà utilisés pour la table de base (votre table "réelle" d'origine) seront utilisés (comme indiqué par l'optimiseur de requête) lorsque vous interrogez chaque vue/scénario. Il n'est pas nécessaire de les redéfinir ou de les copier. Puisqu'une vue est une "fenêtre" (PAS un "shapshot") sur les données "réelles" de la table de base, vous pouvez ajouter/mettre à jour/supprimer sur votre table de base et simplement re-interroger les scénarios de vue sans avoir besoin de recréer quelque chose que les données changent au fil du temps.

Il y a bien sûr un compromis. Comme une vue est une table virtuelle et non une table "réelle" (de base), vous exécutez en fait une requête (peut-être complexe) à chaque fois que vous y accédez. Cela peut ralentir un peu les choses. Mais peut-être pas. Cela dépend de nombreux problèmes (taille et nature des données, qualité des statistiques du catalogue système, vitesse du matériel, charge d'utilisation, etc.). Vous ne saurez pas jusqu'à ce que vous l'essayiez. Si (et seulement si) vous trouvez réellement que la performance est inacceptable, alors vous pourriez regarder d'autres options. (Vues matérialisées, copies de tableaux, ... tout ce qui occupe de l'espace pour le temps.)

+0

J'ai mis à jour la question pour expliquer pourquoi je ne peux pas supprimer de la table originale – Rory

+0

J'ai mis à jour la réponse en fonction de votre contribution. – Alan

89

New PostgreSQL (depuis 8.3 selon docs) peut utiliser ":" Y COMPRIS LES INDICES

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

Comme vous pouvez le voir Je suis en train de tester sur 8.3.

Maintenant, nous allons créer la table:

# 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 

Et voir à quoi il ressemble:

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

Maintenant, nous pouvons copier la structure:

# 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 

et vérifier la structure:

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

Si vous utilisez PostgreSQL pré-8.3, vous pouvez simplement utiliser pg_dump avec l'option "-t" pour spécifier 1 table, nom de la table de changement de décharge, et le charger à nouveau:

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

Et maintenant la table est:

# \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 Une excellente réponse. –

+13

De cette façon, la séquence de clé primaire (x1_id_seq) sera partagée entre les deux tables! – Jauzsika

+2

Ops, avec pg9.X, la séquence de clé primaire sera partagée lors de l'utilisation de "INCLUDING CONSTRAINTS" (pas de "INCLUING INDEXES"). –