Какой лучший способ скопировать подмножество строк таблицы из одной базы данных в другую в Postgres? - PullRequest
7 голосов
/ 06 января 2009

У меня есть производственная база данных, скажем, с десятью миллионами строк. Я хотел бы извлечь приблизительно 10 000 строк из прошедшего часа без производства и скопировать их в мой локальный ящик. Как мне это сделать?

Допустим, запрос:

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

Как мне взять вывод, экспортировать его в какой-нибудь файл дампа, а затем импортировать этот файл дампа в мою локальную копию базы данных разработки - как можно быстрее и проще?

Ответы [ 4 ]

10 голосов
/ 08 июля 2011

Источник:

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

Назначение:

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

Предполагается, что mytable имеет одинаковую схему и порядок столбцов как в источнике, так и в месте назначения. Если это не так, вы можете попробовать STDOUT CSV HEADER и STDIN CSV HEADER вместо STDOUT и STDIN, но я не пробовал.

Если у вас есть собственные триггеры на mytable, вам может потребоваться отключить их при импорте:

psql -c "ALTER TABLE mytable DISABLE TRIGGER USER; \
         COPY mytable FROM STDIN; \
         ALTER TABLE mytable ENABLE TRIGGER USER" < mytable.copy
4 голосов
/ 06 января 2009

исходный сервер:

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;

ваш местный ящик:

-- your_destination_table_here must be created first on your box

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

артикул: http://www.postgresql.org/docs/8.1/static/sql-copy.html

2 голосов
/ 06 января 2009

Из psql вы просто используете copy с запросом, который вы нам дали, экспортируете его как CSV (или любой другой формат), переключаете базу данных с \c и импортируете ее.

Просмотр \h copy в psql.

0 голосов
/ 06 января 2009

С добавленным вами ограничением (не являющимся суперпользователем) я не нахожу решение на чистом SQL. Но сделать это на вашем любимом языке довольно просто. Вы открываете соединение со «старой» базой данных, другое - с новой базой данных, ВЫ выбираете в одной и ВСТАВЛЯЕТЕ в другой. Вот проверенное и работающее решение на Python.

 #!/usr/bin/python

""" 

Copy a *part* of a database to another one. See
</347114/kakoi-luchshii-sposob-skopirovat-podmnozhestvo-strok-tablitsy-iz-odnoi-bazy-dannyh-v-druguy-v-postgres>

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

Stephane Bortzmeyer <bortzmeyer@nic.fr>

"""

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...