繁体   English   中英

使用JDBC在PostgreSQL上缓慢插入

[英]Slow insert on PostgreSQL using JDBC

我在一个系统上工作,该系统将数据从云系统下载到本地数据库(PostgreSQL,MySQL,...)。 现在我遇到了PostgreSQL性能问题,因为插入数据需要花费大量时间。

许多列和数据的大小可能会有所不同。 在一个示例项目中,我有一张大约一张桌子。 170列。 有一个唯一索引 - 但即使在删除索引后,插入的速度也没有改变。

我正在使用JDBC驱动程序连接到数据库,我正在以250行的批量插入数据(使用NamedParameterJdbcTemplate )。

我花了大概。 在Postgres上插入数据需要18秒 MySQL上的相同数据集只花了我一秒钟 这是一个巨大的差异 - 它来自哪里? Postgres JDBC驱动程序是慢的吗? 是否可以以某种方式配置以使其更快? 我错过了别的什么吗? Postgres和MySQL之间的区别是如此巨大。 任何其他想法如何让它更快?

我做了一个示例项目,可以在Github上找到 - https://github.com/varad/postgresql-vs-mysql 一切都发生在LetsGo类的“run”方法中。

看来这是Spring“bug”和驱动程序“bug”的组合。

每次调用setValue()时,Spring都会尝试确定列的数据类型。 它通过调用PreparedStatementMetaData.getParameterMetaData()做到这一点

这显然会导致一个“准备”语句被发送到数据库本身非常快(我的笔记本电脑上的时间不超过1毫秒)但是因为每个的每列调用它总共需要很多时间(这是调用每个非null值,导致大约23.000次调用)

在某种程度上,这更像是一个Spring bug然后是一个驱动程序错误,因为没有缓存参数元数据并不真正有意义(至少在我看来)。 MySQL JDBC驱动程序不支持getParameterMetaData() ,Spring知道这一点,所以这个“bug”没有出现在MySQL中,因为spring从不调用该方法。

我不确定Postgres的JDBC驱动程序行为是否可归类为错误,但如果驱动程序在第一次调用后缓存该元数据,那肯定会很好。

Spring可以说服不通过属性spring.jdbc.getParameterType.ignore获取语​​句元数据

所以通过:

System.setProperty("spring.jdbc.getParameterType.ignore", "true");

在行之前

LetsGo letsGo = new LetsGo();

此行为已禁用。

必须 Spring初始化之前设置该属性。

当我对您的示例项目执行此操作时,插入在我的笔记本电脑上运行500毫秒。


编辑

在看到有关使用Postgres-NG驱动程序的评论之后,我挖掘了“官方”驱动程序和NG驱动程序的来源,并且NG驱动程序在第一次调用后确实缓存了参数元数据,而官方驱动程序没有解释为什么使用NG驱动程序要快得多(不在Spring中禁用调用)

尝试使用pgjdbc-ng驱动程序,然后比较您的结果。

它可以在这里找到: http//impossibl.github.io/pgjdbc-ng/

我希望你使用的是DB Connection Pool。 你可以试试C3P0。 Spring(JDBCTemplate)不提供连接池实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM