如何提高JDBC插入速度?

  如果你需要快速插入insert数据到一个SQL数据库,下面是一些建议:

1. 不要用JDBC

  大部分数据库有自己原生的处理大量插入工具,如果你的数据符合这些工具支持的格式,那么你就很难找到比这个选项更快的方法了。

2.使用Prepared Statements

  Prepared statement通过一次性编译SQL能降低插入时间,而且还能有助于防止SQL注入攻击。一旦一个Prepared statement语句被数据库引擎分析好后,客户端只需要发送需要插入的数据即可,无需每次发送整个SQL语句。

3.使用批插入

  通过某些案例测试发现,使用批处理语句进行100个记录的插入,整体插入时间会从普通的3.5分钟降低到1秒。但是这个方法也有一些缺陷:1). 数据可能不完美,可能会因为重复ID引起一些记录没有插入或重复插入,2).需要将你的原始数据格式转换到符合批处理的数据格式。

DataReader reader = new CSVReader(new File("data/hospital.csv"))
.setFieldNamesInFirstRow(true);
 
reader = new TransformingReader(reader, discardWriter, "error_message")
.add(new RenameField("Provider Number", "hospital_id"))
.add(new BasicFieldTransformer("hospital_id").stringToLong())
.add(new RenameField("Hospital Name", "hospital_name"))
.add(new RenameField("Address 1", "address1"))
.add(new RenameField("Address 2", "address2"))
.add(new RenameField("Address 3", "address3"))
.add(new RenameField("City", "city"))
.add(new RenameField("State", "state"))
.add(new RenameField("ZIP Code", "zip_code"))
.add(new RenameField("County", "county"))
.add(new RenameField("Phone Number", "phone_number"))
.add(new RenameField("Hospital Type", "hospital_type"))
.add(new RenameField("Hospital Ownership", "hospital_ownership"))
.add(new RenameField("Emergency Services", "emergency_services"))
.add(new SetCalculatedField("emergency_services",
"decode(emergency_services, 'Yes', true, 'No', false)"))
;
 
DataWriter writer = new JdbcWriter(getConnection(), "hospital")
.setBatchSize(BATCH_SIZE);
 
Job job = Job.run(reader, writer);
 
System.out.println("Time: " + job.getRunningTimeAsString());

 

4.使用多个连接

  这个取决于你的数据库和配置,使用更多数据库连接用于插入会提高性能,经过测试发现,对于某个大型数据库,将连接提高到5个可以提升速度,但是超过5个就没有什么用处了。

 

5.临时失效一致性约束

  这个主意需要小心,会破坏几个表之间数据的完整性与一致性,失效完整一致性检查意味着你的数据库不会再为每条记录检查数据完整性了,从而提升插入性能,当然不要忘记插入完成后重新激活完整性约束。

 

性能专题

事务机制ACID