2009-01-05 5 views
7

Ich habe eine Produktionsdatenbank mit, sagen wir, zehn Millionen Zeilen. Ich möchte die 10.000 oder mehr Zeilen der letzten Stunde der Produktion extrahieren und sie in meine lokale Box kopieren. Wie mache ich das?Was ist der beste Weg, um eine Teilmenge der Zeilen einer Tabelle in Postgres von einer Datenbank in eine andere zu kopieren?

Lassen Sie uns sagen, dass die Abfrage ist:

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

Wie kann ich den Ausgang nehmen, exportieren Sie ihn auf irgendeine Art von Dump-Datei, und importieren Sie dann die Dump-Datei in meinem lokalen Entwicklung Kopie der Datenbank - wie schnell und einfach wie möglich?

Antwort

2

Von innerhalb psql, verwenden Sie einfach copy mit der Abfrage, die Sie uns gaben, exportieren Sie diese als CSV (oder welches Format auch immer), wechseln Sie die Datenbank mit \c und importieren Sie es.

In \h copy in psql suchen.

+0

Ich erhalte diese: ERROR: muss Superuser sein, um zu kopieren oder aus einer Datei ... gibt es egal wie es geht, vorausgesetzt, ich werde keinen willkürlichen Code als Superuser ausführen können? – mike

+0

Sie sollten die ursprüngliche Frage bearbeiten, um diese Einschränkung hinzuzufügen, um Antworten wie Michael Buen zu vermeiden. – bortzmeyer

0

Mit der Einschränkung hinzugefügt (nicht Superuser), finde ich keine reine SQL-Lösung. Aber es in Ihrer Lieblingssprache zu tun ist ziemlich einfach. Sie öffnen eine Verbindung zur "alten" Datenbank, eine andere zur neuen Datenbank, Sie SELECT in der einen und INSERT in der anderen. Hier ist eine getestete und funktionierende Lösung in 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

Quellserver:

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; 

Ihre lokale Box:

-- your_destination_table_here must be created first on your box 

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

Artikel: http://www.postgresql.org/docs/8.1/static/sql-copy.html

+0

Das OP sagte ausdrücklich (in einem Kommentar zu Keltias Antwort), dass er kein Superuser ist, also ist COPY keine Option). – bortzmeyer

+2

Da der Fragesteller die Frage nicht bearbeitet hat, um Superuser-Constraints zu enthalten, sollte dies als eine gute Antwort betrachtet werden. – Ross

9

Quelle:

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

Reiseziel:

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

Dies setzt voraus, Mytable die beide gleiche Schema und Spaltenreihenfolge in Quelle und Ziel hat. Wenn dies nicht der Fall ist, könnten Sie STDOUT CSV HEADER und STDIN CSV HEADER anstelle von STDOUT und STDIN versuchen, aber ich habe es nicht versucht.

Wenn Sie eine benutzerdefinierte haben auf Mytable auslöst, müssen Sie möglicherweise sie auf Import deaktivieren:

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