我有两个相似的数据库,一个名为datastore
,另一个名为datarestore
。
datarestore
是datastore
的副本,是从备用图片创建的。问题是我不小心从datastore
删除了太多数据。
两个数据库都位于不同的AWS实例上,我通常使用pgAdmin III
或Python连接它们来创建处理数据的脚本。
我想将datastore
中datarestore
意外删除的行datastore
转换为pgAdmin III
。有没有人知道如何实现这一目标。两个数据库都包含接近1.000.000.000行,并且版本为9.6。
我在-----------------------------------------------------
| id (serial - auto incrementing int) | - primary key
| did (varchar) |
| sensorid (int) |
| timestamp (bigint) |
| data (json) |
| db_timestamp (bigint) |
-----------------------------------------------------
内看到了一些备份/导入/恢复选项,我只是不知道它们是如何工作的,以及它们是否支持我的需求?我还考虑过创建一个python脚本,但查询我的数据库变得非常慢,所以这似乎也不是一个选项。
NotificationCenter.default.addObserver(
self,
selector: #selector(self.addressBookDidChange),
name: NSNotification.Name.CNContactStoreDidChange,
object: nil)
答案 0 :(得分:2)
如果您在这些数据库之间保留了主键,那么您可以create foreign tables从datarestore
指向datastore
并检查缺少哪些键(例如使用select pk from old_table except select pk from new_table
)并获取使用您创建的相同外表的那些缺少的行。这应该限制您首次检查丢失的PK只是仅索引扫描(+网络传输),然后它将是索引扫描以获取丢失的数据。如果你只缺少它的一小部分,那么它不应该花很长时间。
如果您需要更详细的示例,我会更新我的答案。
编辑:
这些命令需要在datarestore
(或datastore
上展开,如果您选择推送数据而不是拉动数据。)
如果您还没有安装外部数据包装器:
CREATE EXTENSION postgres_fdw;
这将在datarestore
主机上创建虚拟服务器。它只是指向外部服务器的一些元数据:
CREATE SERVER foreign_datastore FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'foreign_hostname', dbname 'foreign_database_name',
port '5432_or_whatever_you_have_on_datastore_host');
这将告诉您的datarestore
主机在服务器foreign_datastore
上使用fdw时应该连接哪个用户。它仅用于your_local_role_name
登录的datarestore
:
CREATE USER MAPPING FOR your_local_role_name SERVER foreign_datastore
OPTIONS (user 'foreign_username', password 'foreign_password');
您需要在datarestore
上创建架构。这是创建新外国表的地方。
CREATE SCHEMA schema_where_foreign_tables_will_be_created;
这将登录到远程主机并在datarestore
上创建外部表,指向datastore
处的表。只有这样的表才能完成。
不会复制任何数据,只会复制表格。
IMPORT FOREIGN SCHEMA foreign_datastore_schema_name_goes_here
FROM SERVER foreign_datastore INTO schema_where_foreign_tables_will_be_created;
这将返回此表的数据记录数据库中缺少的id
列表
SELECT id FROM foreign_datastore_schema_name_goes_here.table_a
EXCEPT
SELECT id FROM datarestore_schema.table_a
您可以将它们存储在临时表中CREATE TABLE table_a_missing_pk AS [query from above here]
或者马上使用它们:
INSERT INTO datarestore_schema.table_a (id, did, sensorid, timestamp, data, db_timestamp)
SELECT id, did, sensorid, timestamp, data, db_timestamp
FROM foreign_datastore_schema_name_goes_here.table_a
WHERE id = ANY((
SELECT array_agg(id)
FROM (
SELECT id FROM foreign_datastore_schema_name_goes_here.table_a
EXCEPT
SELECT id FROM datarestore_schema.table_a
) sub
)::int[])
从我的测试中,这应该是下推(意味着发送到远程主机)类似的东西:
Remote SQL: SELECT id, did, sensorid, timestamp, data, db_timestamp
FROM foreign_datastore_schema_name_goes_here.table_a WHERE ((id = ANY ($1::integer[])))
您可以通过在完整查询上运行explain verbose
来确保它能够执行,以查看它将执行的计划。你应该在那里看到Remote SQL
。
如果它不能按预期工作,您可以改为创建临时表,如前所述,并确保此临时表位于datastore
主机上。
替代方法是在datastore
上创建指向datarestore
的外部服务器,并将数据从旧数据库推送到新数据库(可以插入到外部表中)。这样您就不必担心id
的列表没有被推到datastore
,而是取出所有数据并在之后过滤它们(这将非常慢)。