2009-01-05 14 views
7

Tengo un DB de producción con, digamos, diez millones de filas. Me gustaría extraer las 10.000 filas de la última hora de producción y copiarlas a mi casilla local. ¿Cómo puedo hacer eso?¿Cuál es la mejor manera de copiar un subconjunto de las filas de una tabla de una base de datos a otra en Postgres?

Digamos que la consulta es:

SELECT * FROM mytable WHERE date > '2009-01-05 12:00:00'; 

¿Cómo se toma la salida, exportarlo a algún tipo de archivo de la descarga, y luego importar ese archivo de volcado en mi copia desarrollo local de la base de datos - como de forma rápida y fácil como sea posible?

Respuesta

2

Desde dentro psql, sólo tiene que utilizar copy con la consulta que nos diste, exportando esto como un archivo CSV (o cualquier formato), base de datos del conmutador con \c e importarlo.

Mire en \h copy en psql.

+0

me sale esto: ERROR: debe ser superusuario para copiar o desde un archivo ... ¿hay de todos modos, suponiendo que no voy a poder ejecutar código arbitrario como superusuario? – mike

+0

Debe editar la pregunta original para agregar esta restricción, para evitar respuestas como Michael Buen's. – bortzmeyer

0

Con la restricción que ha agregado (no es superusuario), no encuentro una solución de SQL puro. Pero hacerlo en tu idioma favorito es bastante simple. Abre una conexión a la base de datos "vieja", otra a la nueva base de datos, SELECCIONA en una e INSERT en la otra. Aquí hay una solución probada y funcional en Python.

#!/usr/bin/python 

""" 

Copy a *part* of a database to another one. See 
<http://stackoverflow.com/questions/414849/whats-the-best-way-to-copy-a-subset-of-a-tables-rows-from-one-database-to-anoth> 

With PostgreSQL, the only pure-SQL solution is to use COPY, which is 
not available to the ordinary user. 

Stephane Bortzmeyer <[email protected]> 

""" 

table_name = "Tests" 
# List here the columns you want to copy. Yes, "*" would be simpler 
# but also more brittle. 
names = ["id", "uuid", "date", "domain", "broken", "spf"] 
constraint = "date > '2009-01-01'" 

import psycopg2 

old_db = psycopg2.connect("dbname=dnswitness-spf") 
new_db = psycopg2.connect("dbname=essais") 
old_cursor = old_db.cursor() 
old_cursor.execute("""SET TRANSACTION READ ONLY""") # Security 
new_cursor = new_db.cursor() 
old_cursor.execute("""SELECT %s FROM %s WHERE %s """ % \ 
         (",".join(names), table_name, constraint)) 
print "%i rows retrieved" % old_cursor.rowcount 
new_cursor.execute("""BEGIN""") 
placeholders = [] 
namesandvalues = {} 
for name in names: 
    placeholders.append("%%(%s)s" % name) 
for row in old_cursor.fetchall(): 
    i = 0 
    for name in names: 
     namesandvalues[name] = row[i] 
     i = i + 1 
    command = "INSERT INTO %s (%s) VALUES (%s)" % \ 
       (table_name, ",".join(names), ",".join(placeholders)) 
    new_cursor.execute(command, namesandvalues) 
new_cursor.execute("""COMMIT""") 
old_cursor.close() 
new_cursor.close() 
old_db.close() 
new_db.close() 
4

servidor de origen:

BEGIN; 

CREATE TEMP TABLE mmm_your_table_here AS 
    SELECT * FROM your_table_here WHERE your_condition_here; 

COPY mmm_your_table_here TO 'u:\\source.copy'; 

ROLLBACK; 

su local de la caja:

-- your_destination_table_here must be created first on your box 

COPY your_destination_table_here FROM 'u:\\source.copy'; 

artículo: http://www.postgresql.org/docs/8.1/static/sql-copy.html

+0

El OP dijo explícitamente (en un comentario a la respuesta de Keltia) que no es superusuario, por lo que COPY no es una opción). – bortzmeyer

+2

Como asker no ha editado la pregunta para contener las restricciones del superusuario, esto se debe considerar como una buena respuesta. – Ross

9

Fuente:

psql -c "COPY (SELECT * FROM mytable WHERE ...) TO STDOUT" > mytable.copy 

Destino:

psql -c "COPY mytable FROM STDIN" < mytable.copy 

Esto supone mitabla tiene el mismo orden de esquema y la columna, tanto en el origen y el destino. Si este no es el caso, puede probar STDOUT CSV HEADER y STDIN CSV HEADER en lugar de STDOUT y STDIN, pero no lo he intentado.

Si tiene cualquier costumbre dispara en mitabla, puede que necesite desactivarlas en la importación:

psql -c "ALTER TABLE mytable DISABLE TRIGGER USER; \ 
     COPY mytable FROM STDIN; \ 
     ALTER TABLE mytable ENABLE TRIGGER USER" < mytable.copy 
Cuestiones relacionadas