我正在运行两个不同的Postgres9.3实例(一个用于生产,一个用于开发/测试)。我想将生产中的表的一个子集复制到开发中。
假设我要复制的表定义为
CREATE TABLE users (user_id varchar PRIMARY KEY, other_stuff varchar);
我要复制的子集是缓存表(在生产环境中)中具有用户id的所有用户,这个表比users表小得多
CREATE TABLE user_id_subset (user_id varchar PRIMARY KEY);
我在我的开发数据库上设置了一些外部表来访问这两个表(分别命名为foreign_users和foreign_user_id_subset),我想执行如下查询:
INSERT INTO development_users (user_id, other_stuff)
SELECT user_id, other_stuff FROM foreign_users f
WHERE EXISTS (
SELECT 1 FROM foreign_user_id_subset ss
WHERE ss.user_id=f.user_id)
这个查询有效,但我担心性能。解释的结果给了我这样的东西:
'Insert on development_users (cost=262.01..284.09 rows=138 width=272)'
' -> Hash Join (cost=262.01..284.09 rows=138 width=272)'
' Hash Cond: ((f.user_id)::text = (cache.user_id)::text)'
' -> Foreign Scan on foreign_users f (cost=100.00..118.28 rows=276 width=272)'
' -> Hash (cost=159.52..159.52 rows=200 width=32)'
' -> HashAggregate (cost=157.52..159.52 rows=200 width=32)'
' -> Foreign Scan on foreign_user_id_subset (cost=100.00..153.86 rows=1462 width=32)'
我认为正在发生的是,我的开发数据库将请求发送到我的生产数据库,这将创建外部用户id子集(生产上的用户id子集)的临时哈希,并在生产上执行哈希检查。这样,通过连接(在数据库之间)发送的唯一东西是初始请求,然后是select查询的结果。这是真的吗?
另一种方法是在我的生产数据库上创建此请求结果的“temp”(不能是真正的临时表b/c,我需要一个外部表),然后构建一个外部表,只需在外部表上执行SELECT*from development。
(需要注意的是,我的生产数据库是一个比我的开发数据库贵得多/性能更好的RDS实例)
最佳答案
回答我自己的问题:
我实现了上面描述的另一个想法:在生产中生成只包含EXISTS查询结果的表,然后在开发中创建一个外部表来引用该表。然后为了创建子集表,我只做了一个“INSERT INTO…SELECT*FROM…”。
使用此方法的时间比发布的原始方法快得多。
创建生产表的时间:Total runtime: 204.838 ms
插入开发数据库的时间:Total runtime: 1564.444 ms
按照原来的方法:
它的速度慢得令人无法接受,需要超过10分钟才能达到与上面相同的结果(我甚至没有等到解释分析完成)
我不知道一种更好的方法来确定经过计划器提供的较低级别指令,但我相信原始方法执行顺序扫描(通过重复扫描外部表的块)并在开发数据库上执行哈希比较。
关于postgresql - PostgreSQL外部表存在子句,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31682841/