我有一個生產數據庫,比如說,有一千萬行。我想從過去的一小時內抽出一萬行左右的行,並將它們複製到我的本地盒子中。我怎麼做?在Postgres中將表的行的子集從一個數據庫複製到另一個數據庫的最佳方法是什麼?
比方說,查詢是:
SELECT * FROM mytable WHERE date > '2009-01-05 12:00:00';
如何採取輸出,它出口某種轉儲文件,然後導入轉儲文件到數據庫中的我的地方發展副本 - 作爲儘可能快捷地進行?
我有一個生產數據庫,比如說,有一千萬行。我想從過去的一小時內抽出一萬行左右的行,並將它們複製到我的本地盒子中。我怎麼做?在Postgres中將表的行的子集從一個數據庫複製到另一個數據庫的最佳方法是什麼?
比方說,查詢是:
SELECT * FROM mytable WHERE date > '2009-01-05 12:00:00';
如何採取輸出,它出口某種轉儲文件,然後導入轉儲文件到數據庫中的我的地方發展副本 - 作爲儘可能快捷地進行?
從psql
內,您只需使用copy
與您給我們的查詢,導出爲CSV(或任何格式),切換數據庫與\c
並導入它。
調查\h copy
psql
。
隨着您添加的約束(不是超級用戶),我找不到純SQL解決方案。但用你最喜歡的語言來做這件事很簡單。你打開一個到「舊」數據庫的連接,另一個連接到新的數據庫,你選擇一個,INSERT在另一個。這裏是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()
源服務器:
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';
來源:
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
我得到這樣的:錯誤:必須是超級用戶複製到或從文件 ...有任何方式,假設我不會以超級用戶身份運行任意代碼? – mike 2009-01-05 23:40:08
您應該編輯原始問題以添加此限制,以避免像邁克爾布恩的答案。 – bortzmeyer 2009-01-06 10:28:48