热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PostgreSQL中批量导入数据的优化方法

本文介绍了在PostgreSQL中批量导入数据时的优化方法。包括使用unlogged表、删除重建索引、删除重建外键、禁用触发器、使用COPY方法、批量插入等。同时还提到了一些参数优化的注意事项,如设置effective_cache_size、shared_buffer等,并强调了在导入大量数据后使用analyze命令重新收集统计信息的重要性。

我们常常需要向数据库中导入数据,如果一次性导入大量的数据必然会对性能产生影响,而且这个时间可能还会特别长。这个可能受多方面的影响,例如:表上存在索引、触发器、磁盘IO等等因素。

那么在PostgreSQL中有什么好的方法来处理批量导入数据这类问题呢,又或者说批量导入数据时我们有哪些优化方法呢?

方法1:修改表为unlogged

pg9.5之后开始支持unlogged表,这个和Oracle中设置表属性为nologging是一样的:让指定的表上进行操作时不产生wal日志。

ALTER TABLE SET UNLOGGED

ALTER TABLE LOGGED

但是由于操作不会产生日志,那么需要注意一旦数据库出现异常导致重启,那么unlogged表中数据将会被清空。
这里说明下:如果数据库是正常关闭的,unlogged表数据是不会丢失的。

除此之外,unlogged表也不会传输到备库,那么就需要在数据导入前停止主备复制,导入完成后再重新同步。

因此在使用unlogged表之前,我们建议:

  • 修改表为unlogged前先进行数据备份;
  • 数据导入后,立刻重新进行数据同步;

方法2:删除并重建索引

索引在批量数据插入过程中可能会造成严重延迟。 这是因为在添加每一行时,相应的索引条目也必须更新。

因此我们建议在开始批量插入之前尽可能地删除目标表中的索引,并在导入完成后重新创建索引。 同样,在大型表上创建索引可能很耗时,但通常比在导入数据期间更新索引要快。

DROP INDEX ,

CREATE INDEX ON (column1, …,column n)

在创建索引之前临时增加maintenance_work_mem配置参数。增加的工作内存可以帮助更快地创建索引。

方法3:删除并重建外键

与索引一样,外键约束也会影响批量负载性能。 这是因为每个插入行中的每个外键都必须检查是否存在相应的主键。 PostgreSQL中内部是使用触发器来执行检查。 所以当加载大量行时,必须为每一行触发此触发器,从而增加开销。

因此一般我们建议将目标表中所有外键删除,在单个事务中加载数据,然后在提交事务后重新创建外键。

ALTER TABLE
DROP CONSTRAINT
BEGIN TRANSACTION

COMMIT
ALTER TABLE
ADD CONSTRAINT
FOREIGN KEY ()
REFERENCES ()...

同样的,增加maintenance_work_mem配置参数可以提高重新创建外键约束的性能。

方法4:禁用触发器

插入或删除触发器(如果加载过程也涉及从目标表中删除记录)可能会导致批量数据加载的延迟。 这是因为每个触发器都有需要检查的逻辑和在插入或删除每一行之后需要完成的操作。

我们建议在批量加载数据之前禁用目标表中的所有触发器,并在加载完成后启用它们。禁用所有触发器还包括强制执行外键约束检查的系统触发器。

ALTER TABLE DISABLE TRIGGER ALL

ALTER TABLE ENABLE TRIGGER ALL

方法5:使用COPY方法

使用COPY命令从一个或多个文件加载数据。COPY针对批量数据加载进行了优化。它比运行大量的插入语句,甚至是多值插入,更有效。pg12开始支持在copy命令中增加where过滤,使用起来也更加灵活。

COPY [( column1>, … , )]
FROM ''
WITH (, , … , )

方法6:使用批量插入

执行多个insert语句进行插入的性能远远不如批量插入。这是因为每个单独的insert命令都必须由查询优化器解析和准备,通过所有约束检查,作为一个单独的事务运行,并产生WAL日志。 使用批量INSERT语句可以节省此开销。

INSERT INTO (, , …, )
VALUES
(, , …, ),
(, , …, ),
(, , …, ),
(, , …, ),
...

与之类似的是,我们可以关闭pg中的自动提交,来手动进行批量的提交。而不是每执行一条语句就进行一次提交,而是将多条语句放在一个事务中。

这里我们可以设置commit_delay来实现,指定提交状态的事务达到commit_siblings时进行一次性提交,这样只需要flush一次wal日志,从而减少wal io。

方法7:其它注意事项

除此之外,我们可以对一些参数进行优化,例如:设置effective_cache_size 为内存的50%,设置shared_buffer为内存的25%,还可以适当增加max_wal_size。

还有最后一点需要注意的是:
批量导入大量数据后记得使用analyze命令来重新收集统计信息。


推荐阅读
  • egg实现登录鉴权(七):权限管理
    权限管理包含三部分:访问页面的权限,操作功能的权限和获取数据权限。页面权限:登录用户所属角色的可访问页面的权限功能权限:登录用户所属角色的可访问页面的操作权限数据权限:登录用户所属 ... [详细]
  • Gradle 是 Android Studio 中默认的构建工具,了解其基本配置对于开发效率的提升至关重要。本文将详细介绍如何在 Gradle 中定义和使用共享变量,以确保项目的一致性和可维护性。 ... [详细]
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • binlog2sql,你该知道的数据恢复工具
    binlog2sql,你该知道的数据恢复工具 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 本文探讨了如何通过优化 DOM 操作来提升 JavaScript 的性能,包括使用 `createElement` 函数、动画元素、理解重绘事件及处理鼠标滚动事件等关键主题。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 本文详细介绍了JQuery Mobile框架中特有的事件和方法,帮助开发者更好地理解和应用这些特性,提升移动Web开发的效率。 ... [详细]
  • 本文探讨了如何使用Scrapy框架构建高效的数据采集系统,以及如何通过异步处理技术提升数据存储的效率。同时,文章还介绍了针对不同网站采用的不同采集策略。 ... [详细]
  • 本文详细介绍了MySQL InnoDB存储引擎中的Redo Log和Undo Log,探讨了它们的工作原理、存储方式及其在事务处理中的关键作用。 ... [详细]
  • 本文探讨了使用Python实现监控信息收集的方法,涵盖从基础的日志记录到复杂的系统运维解决方案,旨在帮助开发者和运维人员提升工作效率。 ... [详细]
  • 本文探讨了互联网服务提供商(ISP)如何可能篡改或插入用户请求的数据流,并提供了有效的技术手段来防止此类劫持行为,确保网络环境的安全与纯净。 ... [详细]
  • Hibernate全自动全映射ORM框架,旨在消除sql,是一个持久层的ORM框架1)、基础概念DAO(DataAccessorOb ... [详细]
  • Docker安全策略与管理
    本文探讨了Docker的安全挑战、核心安全特性及其管理策略,旨在帮助读者深入理解Docker安全机制,并提供实用的安全管理建议。 ... [详细]
  • 本文介绍了SELinux的两种主要工作模式——强制模式和宽容模式,并提供了如何在CentOS 7中正确启用和配置SELinux的方法,以及在遇到登录问题时的解决策略。 ... [详细]
author-avatar
未来不是梦2602932127
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有