2008-10-13 9 views
72

Tengo una tabla de postgres. Necesito borrar algunos datos de él. Iba a crear una tabla temporal, copiar los datos, recrear los índices y eliminar las filas que necesito. No puedo eliminar datos de la tabla original, porque esta tabla original es la fuente de datos. En un caso, necesito obtener algunos resultados que dependen de eliminar X, en otro caso, necesitaré eliminar Y. Por lo tanto, necesito que todos los datos originales estén siempre disponibles.Copie una tabla (incluidos los índices) en postgres

Sin embargo, parece un poco tonto recrear la tabla y copiarla de nuevo y volver a crear los índices. ¿Hay alguna forma en postgres que diga "Quiero una copia completa de esta tabla, incluida la estructura, los datos y los índices"?

Desafortunadamente PostgreSQL no tiene una tabla "CREATE .. como

Respuesta

1

Crear una nueva tabla utilizando un selecto para agarrar los datos que desea. A continuación, cambiar la mesa de edad con el nuevo.

X incluidos los índices'
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] 

Aquí es un example

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

La otra forma para crear una nueva tabla a partir de la primera es utilizar

CREATE TABLE films_recent (LIKE films INCLUDING INDEXES); 

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

Tenga en cuenta que PostgreSQL tiene un patch a cabo para solucionar los problemas de espacio de tabla si se utiliza el segundo método

+0

No hay "ÍNDICES INCLUIDOS" en postgres. – Rory

+2

¿Qué versión estás usando? Lea el último documento, está allí – WolfmanDragon

+6

con pg9.X, cuando se usa "INCLUYENDO RESTRICCIONES" (no "INCLUYENDO ÍNDICES"), la secuencia de teclas principal se compartirá entre las dos tablas (!). –

4

Tengo una tabla postgres. Necesito borrar algunos datos del mismo.

Supongo que ...

delete from yourtable 
where <condition(s)> 

... no va a funcionar por alguna razón. (Cuidado para compartir esa razón?)

que iba a crear una tabla temporal , copie los datos en, volver a crear los índices y la elimina las filas que necesidad.

Mire en pg_dump y pg_restore. Usar pg_dump con algunas opciones inteligentes y tal vez editar la salida antes de pg_restoring podría hacer el truco.


Ya que haces "y si" el análisis de tipo en los datos, me pregunto si podría estar mejor de usar puntos de vista.

Puede definir una vista para cada escenario que desee probar en función de la negación de lo que desea excluir. Es decir, defina una vista en función de lo que desea INCICLAR. Por ejemplo, si quiere una "ventana" en los datos donde "eliminó" las filas donde X = Y, entonces crearía una vista como filas donde (X! = Y).

Las vistas se almacenan en la base de datos (en el Catálogo del sistema) como su consulta de definición. Cada vez que consulta la vista, el servidor de la base de datos busca la consulta subyacente que la define y la ejecuta (AND con cualquier otra condición que haya utilizado).Este enfoque ofrece varias ventajas:

  1. Nunca duplica ninguna parte de sus datos.
  2. Los índices que ya están en uso para la tabla base (su tabla original, "real") se usarán (según lo considere el optimizador de consultas) cuando consulte cada vista/escenario. No es necesario redefinirlos ni copiarlos.
  3. Como una vista es una "ventana" (NO una captura) de los datos "reales" en la tabla base, puede agregar/actualizar/eliminar en su tabla base y simplemente volver a consultar los escenarios de vista sin necesidad de recrear cualquier cosa a medida que los datos cambian con el tiempo.

Hay un compromiso, por supuesto. Como una vista es una tabla virtual y no una tabla "real" (base), en realidad está ejecutando una consulta (tal vez compleja) cada vez que accede a ella. Esto puede desacelerar un poco las cosas. Pero puede que no. Depende de muchos problemas (tamaño y naturaleza de los datos, calidad de las estadísticas en el catálogo del sistema, velocidad del hardware, carga de uso y mucho más). No lo sabrás hasta que lo pruebes. Si (y solo si) realmente encuentra que el rendimiento es inaceptablemente lento, entonces puede ver otras opciones. (Las vistas materializadas, copias de las tablas, ... cualquier cosa que comercia espacio de tiempo.)

+0

He actualizado la pregunta para explicar por qué no puedo simplemente eliminar de la tabla original – Rory

+0

He actualizado la respuesta en función de su información adicional. – Alan

89

Nueva PostgreSQL (desde 8,3 acuerdo con documentos) puede utilizar "incluidos los índices":

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

Como se puede ver Estoy probando en 8.3.

Ahora, vamos a crear la tabla:

# 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 

Y ver cómo se ve:

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

Ahora podemos copiar la estructura:

# 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 

Y comprobar la estructura:

# \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 está utilizando PostgreSQL pre-8.3, puede simplemente usar pg_dump con la opción "-t" para especificar el 1 de mesa, mesa de cambio de nombre en el basurero, y cargarlo de nuevo:

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

Y ahora la tabla es:

# \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 Una gran respuesta. –

+13

¡De esta manera, la secuencia de teclas principal (x1_id_seq) se compartirá entre las dos tablas! – Jauzsika

+2

Ops, con pg9.X, la secuencia de teclas principal se compartirá cuando se usa "INCLUYENDO RESTRICCIONES" (no "INCLUYENDO ÍNDICES"). –

Cuestiones relacionadas