我们很难一次插入很多行。
我们正在将项目运行到localhost MySQL数据库的计算机上,以确保服务器的性能不成问题。
这么长的插入时间有什么关系吗?
代码中的注释准确地说明了导致我们出现问题的那一行
public <T> void batchExecute(String query, BatchArgSetter<T> batchArgSetter) {
Connection con = this.getConnection();
PreparedStatement statement = null;
int i = 0;
try {
con.setAutoCommit(false);
statement = con.prepareStatement(query);
while (batchArgSetter.hasNext()) {
// This code to set args and add batch is instant. About 0.05 ms per per 1000.
setArgs(statement, batchArgSetter.getArgs(batchArgSetter.next()));
statement.addBatch();
i++;
if (i % 1000 == 0 || i == batchArgSetter.getSize()) {
// However, this line takes forever.
// About 30 seconds per batch. A test with 9600 entries took a total time of 5min 42sec
// We tried testing a collection of 100k+ entries, which we stopped after id had run 10min +
statement.executeBatch();
con.commit();
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll(statement, null, con);
}
}
public class SqlConnection {
private String username;
private String password;
private String url;
private HikariConfig config = new HikariConfig();
private HikariDataSource ds;
public SqlConnection(Setting.PersistenceSetting setting) {
this.username = setting.getUsername();
this.password = setting.getPassword();
this.url = "jdbc:mysql://" + setting.getUrl() + ":" + setting.getPort() + "/" + setting.getDatabase() + "?serverTimezone=UTC";
setup(setting.getPoolSize());
}
private void setup(int poolSize) {
config.setJdbcUrl(url);
config.setUsername(username);
config.setPassword(password);
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.setMaximumPoolSize(poolSize);
config.setLeakDetectionThreshold(2000);
config.setAutoCommit(true);
ds = new HikariDataSource(config);
}
private void insertMembers(List<Member> members) {
sql.batchExecute("INSERT INTO user VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE username = ?, discriminator = ?, avatar = ?;", new BatchArgSetter<Member>(members) {
@Override
public Object[] getArgs(Member m) {
return new Object[]{
m.getIdLong(),
m.getUser().getName(),
m.getUser().getDiscriminator(),
m.getUser().getEffectiveAvatarUrl(),
m.getUser().getName(),
m.getUser().getDiscriminator(),
m.getUser().getEffectiveAvatarUrl()
};
}
});
sql.batchExecute("INSERT INTO guild_member VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE nickname=?", new BatchArgSetter<Member>(members) {
@Override
public Object[] getArgs(Member member) {
return new Object[]{
member.getIdLong(),
member.getGuild().getIdLong(),
member.getNickname(),
member.getNickname()
};
}
});
}