我正在努力提高我的java应用程序的性能,现在我将重点放在一个端点上,这个端点必须向mysql中插入大量数据。
我将普通jdbc与mariadb java客户端驱动程序结合使用:
try (PreparedStatement stmt = connection.prepareStatement(
"INSERT INTO data (" +
"fId, valueDate, value, modifiedDate" +
") VALUES (?,?,?,?)") {
for (DataPoint dp : datapoints) {
stmt.setLong(1, fId);
stmt.setDate(2, new java.sql.Date(dp.getDate().getTime()));
stmt.setDouble(3, dp.getValue());
stmt.setDate(4, new java.sql.Date(modifiedDate.getTime()));
stmt.addBatch();
}
int[] results = statement.executeBatch();
}
从转储文件中填充新数据库,我知道 max_allowed_packet
很重要,我把它设为536870912字节。
在https://dev.mysql.com/doc/refman/5.7/en/insert-optimization.html 它指出:
如果要同时从同一客户机插入多行,请使用具有多个值列表的insert语句一次插入多行。这比使用单独的单行insert语句快得多(在某些情况下快很多倍)。如果要向非空表中添加数据,可以调整bulk\u insert\u buffer\u size变量,使数据插入更快。参见第5.1.7节“服务器系统变量”。
在我的dbs上,这个设置为8mb
我也读过 key_buffer_size
(当前设置为16mb)。
我担心最后两个可能不够。我可以对这个算法的json输入做一些粗略的计算,因为它看起来像这样:
[{"actualizationDate":null,"data":[{"date":"1999-12-31","value":0},
{"date":"2000-01-07","value":0},{"date":"2000-01-14","value":3144},
{"date":"2000-01-21","value":358},{"date":"2000-01-28","value":1049},
{"date":"2000-02-04","value":-231},{"date":"2000-02-11","value":-2367},
{"date":"2000-02-18","value":-2651},{"date":"2000-02-25","value":-
393},{"date":"2000-03-03","value":1725},{"date":"2000-03-10","value":-
896},{"date":"2000-03-17","value":2210},{"date":"2000-03-24","value":1782},
它看起来像是为 bulk_insert_buffer_size
很容易被超过,如果不是的话 key_buffer_size
也。
但是mysql文档只提到 MyISAM
引擎表,我现在正在使用 InnoDB
table。
我可以设置一些测试,但它会很好地知道这将如何打破或降级,如果在所有。
[编辑]我有 --rewriteBatchedStatements=true
. 实际上,这是我的连接字符串:
jdbc:p6spy:mysql://myhost.com:3306/mydb\
?verifyServerCertificate=true\
&useSSL=true\
&requireSSL=true\
&cachePrepStmts=true\
&cacheResultSetMetadata=true\
&cacheServerConfiguration=true\
&elideSetAutoCommits=true\
&maintainTimeStats=false\
&prepStmtCacheSize=250\
&prepStmtCacheSqlLimit=2048\
&rewriteBatchedStatements=true\
&useLocalSessionState=true\
&useLocalTransactionState=true\
&useServerPrepStmts=true
(来自https://github.com/brettwooldridge/hikaricp/wiki/mysql-configuration )
1条答案
按热度按时间oiopk7p51#
另一种方法是不时地执行批处理。这允许您减小批处理的大小,并让您将精力集中在更重要的问题上。
我通常使用基于dao实现的常量或参数来提高动态性,但是一批10000行是一个很好的开始。
请注意,执行后不必清除批处理。即使没有在
Statement.executeBatch
文档,这在jdbc规范4.3中14批更新
14.1批量更新说明
14.1.2成功执行
调用方法executebatch将关闭调用语句对象的当前结果集(如果其中一个结果集已打开)。
一旦executebatch返回,语句的批处理将重置为空。
结果的管理有点复杂,但是如果需要,仍然可以连接结果。这可以在任何时候进行分析,因为
ResultSet
不再需要了。