将大量行追加到单个表中的最佳方法是什么



我正在开发一种产品,该产品将大量的追加销售操作整合到一个表中。

我们正在处理基于时间的数据,并使用具有7天块间隔大小的timescaledb超表。我们有将数据打乱到单个表中的并发任务,在极端情况下,我们可能会有40个并发任务,每个任务打乱大约250k行,全部打乱到同一个表中。

最初,我们决定删除所有旧行,然后用COPY FROM语句插入更新的行,但当我们大规模测试系统时,这些COPY需要很长时间才能完成,最终导致数据库的CPU使用率达到100%,并且变得没有响应。我们还注意到,表的索引大小急剧增加,磁盘使用率达到100%,并且SELECT语句的执行时间非常长(超过10分钟(。我们得出的结论是,造成这种情况的原因是大量的删除语句导致了索引碎片,并决定采用另一种方法。

根据这篇文章的答案,我们决定将所有数据复制到一个临时表中,然后使用";延伸插入件";声明-

INSERT INTO table SELECT * FROM temp_table ON CONFLICT DO UPDATE...; 

我们的测试表明,它有助于解决索引碎片问题,但仍有约250K的大型追加启动操作需要4分钟以上才能执行,并且在追加启动过程中,SELECT语句需要很长时间才能完成,这对我们来说是不可接受的

我想知道创建这种对SELECT性能影响尽可能小的追加启动操作的最佳方法是什么。现在唯一想到的是将插入分成更小的块-

INSERT INTO table SELECT * FROM temp_table LIMIT 50000 OFFSET 0 ON CONFLICT DO UPDATE ...;
INSERT INTO table SELECT * FROM temp_table LIMIT 50000 OFFSET 50000 ON CONFLICT DO UPDATE ...;
INSERT INTO table SELECT * FROM temp_table LIMIT 50000 OFFSET 100000 ON CONFLICT DO UPDATE ...;
...

但是,如果我们批量插入,那么首先将所有数据复制到临时表中有什么好处吗?它的性能会比简单的多行插入语句更好吗?在拆分upstart时,我如何决定使用什么样的最佳块大小?是使用临时表并直接从中打乱行可以获得更大的块大小吗?

有没有更好的方法来实现这一点?如有任何建议,将不胜感激

您可以做一些事情来加快数据加载:

  • 加载数据时,表上没有索引或外键(检查约束很好(。我并不是建议您放弃所有约束,但您可以使用分区,将数据加载到一个新表中,然后创建索引和约束,并将表作为一个新分区附加。

  • COPY加载数据。如果不能使用COPY,请使用为INSERT准备的语句来节省解析时间。

  • 在一个事务中加载多行。

  • max_wal_size设置为高,这样您就不会得到超出需要的检查点。

  • 获取快速本地磁盘。

相关内容

最新更新