Postgres花费很长时间保存具有空值的批处理更新

问题描述

我在这里进一步扩展问题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 ”的调用提供的显式类型数组,通过“ registerSqlType”显式指定相应的JDBC类型。调用自定义'MapSqlParameterSource'实例,或通过'BeanPropertySqlParameterSource'调用,Bean甚至从null值中也从Java声明的属性类型中获取SQL类型。

我创建了spring.properties并添加了spring.jdbc.getParameterType.ignore=true解决了我的问题,现在只需7-10秒即可将1800条记录加载到3个不同的表中,这些表的10列中有5列为NULL值。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...