【发布时间】:2018-08-26 13:57:29
【问题描述】:
假设有一个表customers,它有以下列:
customer_id 作为主键
创作日期
其他几列
我想使用 creation_date >= to_date('2000/01/01', 'YYYY/MM/DD') 查询客户表中的所有条目并插入到另一个表客户端中。 客户表中的条目数约为 1000 万,并且两个表都在同一个数据库中。 我想尽量减少复制这些数据的时间。
有两种方法:
-
对每个 n 并行运行以下查询,其中 n = 1、10001、20001... 以此类推
insert into clients values ( select * from ( select *, row_number() over (ORDER BY customer_id) as rn from ( select * from customers where creation_date >= to_date('2000/01/01', 'YYYY/MM/DD') ) as sub1 ) as sub2 where rn>=n limit 10000 ); -
运行单个查询
insert into clients values ( select * from customers where creation_date >= to_date('2000/01/01', 'YYYY/MM/DD') );
对于1,以下是执行计划
在客户端上插入(成本=0.42..113.55 行=10000 宽度=4506) -> 对“*SELECT*”进行子查询扫描(成本=0.42..113.55 行=10000 宽度=4506) -> 限制(成本=0.42..112.45 行=10000 宽度=616) -> sub2 上的子查询扫描(成本=0.42..57773.19 行=1000000 宽度=616) 过滤器:(sub2.rn >= 0) -> WindowAgg(成本=0.42..57579.79 行=1000000 宽度=624) -> 对客户使用“customer_id_pkey”进行索引扫描(成本=0.42..57347.71 行=1000000 宽度=616) 过滤器: ((creation_date >= to_date('2000/01/01'::text, 'YYYY/MM/DD'::text))对于所有 n 并行执行,sub2 上的子查询扫描 将在整个数据上运行。因此,并行执行它已经破坏了目的。
我的理解是否正确,或者接近 1 所花费的时间比接近 2 的时间要短。
另外请建议是否有提高查询性能的方法。
[计划节点的值已被修改,因此请忽略行、成本和宽度值]
【问题讨论】:
-
数据库大小是相对的。如果您的服务器相当强大,或者负载较低,或者记录大小较小,则 1000 万不一定很大。如果 其中任何一个 是真的,那么你可能真的想多了。如果 没有 为真,您可能需要更多资源用于您的数据库服务器。
-
如果查询返回多于一行,插入将不起作用。如果您想基于 select 使用
insert删除values子句 - 只允许单行。
标签: sql postgresql