使用postgres插入/复制锁定和阻塞的并行聚合

时间:2015-06-02 23:31:22

标签: postgresql parallel-processing locking bulkinsert blocking

我需要进行大量计算,然后将结果插入postgres数据库。我使用并行聚合进行计算并按处理器计数对其进行分片。

我注意到每个周期,前5分钟,cpu利用率为100%,因为所有核心都在进行计算。然后在接下来的30分钟内,所有数据都被不同的线程复制到postgres中,相互阻塞......想知道我应该做些什么来优化它。 Sharding在这里不是一个真正的选择,因为我们已经按日期划分了表格,不想通过PersonId再次对它进行分片来使它变得太复杂......

有没有办法解决这个问题?是否可以将数据放入单个队列并让postgres处理队列?

更多细节: 在每个线程中,它做两件事: 1)调用数据服务进行计算,并返回结果集 2)将结果集复制到数据库表(Kpis_weekly)

我们启动N(N =处理器计数)线程来执行上述过程,数据按personId进行分片,因此它们大致均匀地分布在所有线程上。瓶颈是数据库表。所有这些线程都必须插入到同一个表中,因此它们会相互阻塞并减慢整个过程。

1 个答案:

答案 0 :(得分:0)

问题(正如OP正确指出的那样)是将线程生成的所有写入汇集到一个表中可能是瓶颈。

我们在这里做的是尽管使用PARTITION(主要帮助读取/ SELECT语句),但写入是NOT触发器。所以,是的,'做'意味着将生成表名的逻辑移动到线程,但对我们来说,这是真的'值得努力。

因此,例如以下代码直接写入子表(而不是父表),但重要的是写入有效地并行化。显然,写入是I / O绑定的,因此磁盘越快,写入越快。以下SQL实际上是使用并行线程(即使是写入)而不是数据库瓶颈(但是磁盘子系统)。

SQL

create UNLOGGED table p(a integer);
create UNLOGGED table c1() INHERITS (p);
create UNLOGGED table c2() INHERITS (p);
create UNLOGGED table c3() INHERITS (p);
create UNLOGGED table c4() INHERITS (p);
create UNLOGGED table c5() INHERITS (p);
create UNLOGGED table c6() INHERITS (p);
create UNLOGGED table c7() INHERITS (p);
create UNLOGGED table c8() INHERITS (p);

通过shell脚本

psql -c "INSERT INTO c1 select a from generate_series (1,10000000) as e(a);" &
psql -c "INSERT INTO c2 select a from generate_series (1,10000000) as e(a);" &
psql -c "INSERT INTO c3 select a from generate_series (1,10000000) as e(a);" &
psql -c "INSERT INTO c4 select a from generate_series (1,10000000) as e(a);" &
psql -c "INSERT INTO c5 select a from generate_series (1,10000000) as e(a);" &
psql -c "INSERT INTO c6 select a from generate_series (1,10000000) as e(a);" &
psql -c "INSERT INTO c7 select a from generate_series (1,10000000) as e(a);" &
psql -c "INSERT INTO c8 select a from generate_series (1,10000000) as e(a);" &

INSERT之后,对于所有(子级+父级)表,您可能希望将它们转换为LOGGED表( PostgreSQL 9.5 + ):

ALTER TABLE p SET LOGGED;