问题描述
我在这里进一步扩展问题Spring Batch Performance issue when run two independent jobs sequentially?:
我们看到了Postgres v9.6的行为,我们试图使用批处理更新来保存具有空值的数据,这需要花费很长时间来保存数据。
是否可以从数据库端或从Spring Boot端对其进行修复?
样本查询-
"INSERT INTO test.ACCT "
+ "(rec_type,acct_type_cd,src_acct_id,stat_cd,stat_dttm,........,"
+ "..................) "
+ "VALUES(?,?,)";
注意-出于安全原因,不能按原样添加列名称。
我们有下表的详细信息和查询
- 在几列中有很大一部分的NULL
- 定期接收大量的UPDATE或DELETE
- 增长不快
- 没有索引。
- 不使用任何可能正在执行数据库函数或直接调用函数的触发器
总编号我们分批插入的行数为40K,并包含2500条记录。 码 列表
batchValues = new ArrayList<>(items.size());
for(Employee emp: items) {
batchValues.add(new MapSqlParameterSource()
.addValue("",emp.getXXXXX() == null ? "": emp.getXXXXX(),JDBCType.VARCHAR.getVendorTypeNumber())
.addValue("",emp.getXXXXX(),JDBCType.DATE.getVendorTypeNumber())
.addValue("",emp.getXXXXX()== null ? "": emp.getXXXXX(),JDBCType.VARCHAR.getVendorTypeNumber())
........
........
........
........
.getValues());
}
try {
int[] updateCounts = namedJdbcTemplate.batchUpdate(SQL,batchValues.toArray(new Map[items.size()]));
} catch (Exception e) {
log.error("Error occurred in BatchUpdate ##");
throw new GenericException(e.getMessage(),this.getClass().getSimpleName());
}
批处理作业按顺序运行,首先是截断(这是快速的),而其他批处理插入(具有更多的空值)会耗尽性能。
解决方法
感谢 M的帮助。 Deinum 和 a_horse_with_no_name 总是能提供很大的帮助。
如此处Slow insert on PostgreSQL using JDBC和第5.3.2节-https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#jdbc-batch-list所建议。
在这种情况下,通过在基础PreparedStatement上自动设置值,需要从给定的Java类型派生每个值的对应JDBC类型。尽管这通常效果很好,但存在潜在的问题(例如,包含Map的空值)。在这种情况下,Spring默认情况下会调用ParameterMetaData.getParameterType,这对于JDBC驱动程序可能会很昂贵。如果遇到性能问题,应使用最新的驱动程序版本,并考虑将spring.jdbc.getParameterType.ignore属性设置为true(作为JVM系统属性或在类路径根目录中的spring.properties文件中)。 ,如Oracle 12c(SPR-16139)所述。
或者,您可以考虑通过“ BatchPreparedStatementSetter”(如先前所示),通过为基于“ List
我创建了spring.properties
并添加了spring.jdbc.getParameterType.ignore=true
解决了我的问题,现在只需7-10秒即可将1800条记录加载到3个不同的表中,这些表的10列中有5列为NULL值。