假设有一个表客户,它有以下列:
customer_id作为主键
CREATION_DATE
几乎没有其他专栏
我想使用creation_date> = to_date(' 2000/01 / 01',' YYYY / MM / DD')查询customers表中的所有条目并插入另一个表客户。 表客户中的条目数约为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,以下是执行计划
Insert on clients (cost=0.42..113.55 rows=10000 width=4506) -> Subquery Scan on "*SELECT*" (cost=0.42..113.55 rows=10000 width=4506) -> Limit (cost=0.42..112.45 rows=10000 width=616) -> Subquery Scan on sub2 (cost=0.42..57773.19 rows=1000000 width=616) Filter: (sub2.rn >= 0) -> WindowAgg (cost=0.42..57579.79 rows=1000000 width=624) -> Index Scan using “customer_id_pkey" on customers (cost=0.42..57347.71 rows=1000000 width=616) Filter: ((creation_date >= to_date('2000/01/01'::text, 'YYYY/MM/DD'::text))
对于所有并行执行, sub2 上的子查询扫描将对整个数据运行。因此,并行执行已经打败了目的。
我的理解是正确的还是接近1会比接近2更少的时间。
另外请建议是否有办法提高查询性能。
[计划节点的值已被修改,因此请忽略行,成本和宽度值]
答案 0 :(得分:0)
这更像是一个扩展评论。
你应该尝试不同的方法,看看哪种方法效果最好。就个人而言,我会采用第二种方法,尽管我会把它写成:
insert into clients ( . . .)
select c.*
from customers c
where creation_date >= date '2000-01-01';
为什么呢?在表中执行多个insert
会生成表争用,日志争用和可能的索引争用。这可能会减慢速度。我不是说它会 - 只是不考虑它,我只是开始查询并等待它需要多长时间(一杯咖啡?午餐?过夜?)
如果您的数据非常大,那么您可能想要考虑对数据进行分区。如果是这种情况,那么多个同时插入是个好主意 - 只要它们都进入单个分区。
顺便说一句,在您的第一个版本中,您不需要使用row_number()
。您可以使用offset
/ fetch
语法来获取不同的数据。