我正在进行一项实验,我希望看到将多个记录插入PostgreSQL数据库的方法将为我提供最佳的速度性能。我正在使用" PostgreSQL 9.5.3,由Visual C ++ build 1800,64位"编译。 + Java 1.8 + Postgres JDBC驱动程序9.4.1207。
此实验的表定义如下:
CREATE TABLE mytable (ea VARCHAR(256) NOT NULL, ehv CHAR(60) NOT NULL);
ALTER TABLE mytable ADD CONSTRAINT pk_mytable_ea PRIMARY KEY (ea);
第一种方法是执行executeBatch
,我在其中创建参数映射列表。代码如下所示:
public void executeBatch(List<MyObject> myObjects) {
final String sql = "INSERT INTO mytable(" +
" ea, ehv) " +
" VALUES (:ea, :ehv) ";
MapSqlParameterSource[] params = new MapSqlParameterSource[myObjects.size()];
for (int i = 0; i < myObjects.size(); i++) {
params[i] = new MapSqlParameterSource()
.addValue("ea", myObjects.get(i).getEa())
.addValue("ehv", myObjects.get(i).getEhv());
}
jdbcTemplate.batchUpdate(sql, params);
}
第二种方法更具异国情调,它使用Jackson
将对象序列化为jsonb
,然后使用jsonb_to_recordset
我扩展此{{ {1}}字符串到记录行,然后我将其插入JSON
。
mytable
我使用以下测试对这两种方法进行了比较,其中我创建了10,000个MyObjects。
public void insertFromString(List<MyObject> myObjects) throws RepositoryException {
final String sql = "INSERT INTO mytable(ea, ehv)\n" +
"select ea, ehv\n" +
"from jsonb_to_recordset(:myObjectsJson) as x(ea text, ehv text)\n" +
"ON CONFLICT DO NOTHING";
ObjectMapper jsonObjectMapper = new ObjectMapper();
String myObjectsJson = null;
try {
myObjectsJson = jsonObjectMapper.writeValueAsString(myObjects);
} catch (JsonProcessingException ex) {
throw new RepositoryException("Error while transforming myObjects to json.", ex);
}
PGobject jsonObject = new PGobject();
jsonObject.setType("jsonb");
try {
jsonObject.setValue(myObjectsJson);
} catch (SQLException ex) {
throw new RepositoryException("Error while building jsonb object.", ex);
}
jdbcTemplate.update(sql, new MapSqlParameterSource().addValue("myObjectsJson", jsonObject));
}
运行测试我发现第二种方法表现更好:
@Test
public void test() throws JsonProcessingException, RepositoryException {
List<MyObject> myObjects = new ArrayList(10000);
for(int i = 0; i < 10000; i++) {
myObjects.add(new MyObject(i + "ea", i + "ehv"));
}
long before = System.currentTimeMillis();
censusRepository.executeBatch(myObjects);
long after = System.currentTimeMillis();
System.out.println("executeBatch Took - " + (after-before));
namedParameterJdbcTemplate.update("delete from mytable", new MapSqlParameterSource());
before = System.currentTimeMillis();
censusRepository.insertFromString(myObjects);
after = System.currentTimeMillis();
System.out.println("insertFromString Took - " + (after-before));
namedParameterJdbcTemplate.update("delete from mytable", new MapSqlParameterSource());
}
是什么导致第二种方法的表现比executeBatch Took - 464ms
insertFromString Took - 253ms
好得多?根据您的经验,我应采取哪种方法。你能建议另一个,这可以给我更好的表现吗?我有以下约束 - 我将在数据库中插入1000个MyObjects批次,每个MyObject包含两个String值。