与从 IDE 或 mysql 命令行调用相比,通过 JDBC 调用时,我看到 mysql 插入时间的执行速度要慢几个数量级,我想知道是否有人能指出我正确的方向。
我在本地运行所有内容,因此网络延迟应该不是问题。
我创建了以下非常人为的示例来说明这一点。
我创建了一个存储过程,它接受单个 INT 并将其插入到表中:
DELIMITER $$
CREATE PROCEDURE testInsert(IN input INT)
BEGIN
INSERT INTO test_table(column_1, column_2)
VALUES(input, input);
END$$
DELIMITER ;
如果我要从命令行或 mysql IDE(我正在使用 SQLyog)调用此过程:
CALL testInsert(0);
出于所有意图和目的,过程调用立即发生:
Execution Time : 0.007 sec
Transfer Time : 0.001 sec
Total Time : 0.009 sec
但是,如果要从 Java 调用该过程,请使用以下代码:
public void testStoredProcedureInsert() throws SQLException{
//custom class for managing the sql and variables on the prepared statement
SQLStatementBinder sqlBinder = new SQLStatementBinder();
sqlBinder.appendSql("CALL testInsert(?)");
//will store the object into a collection in the sql binder
sqlBinder.addBindVariable(0);
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/dbname", "user", "pass");
CallableStatement stmt = connection.prepareCall(sqlBinder.getSQL());
//bindSql loops through bind variables and sets the appropriate parameters based on the type of the objects - in this case only preparedStatement.setInt(1, 0) is called.
stmt = (CallableStatement)sqlBinder.bindSql(stmt);
long start = System.currentTimeMillis();
stmt.executeQuery();
long end = System.currentTimeMillis();
System.out.println("time to call procedure - " + (end-start) + "ms");
}
更新的运行时间(请注意,我只对实际执行进行计时,因此不考虑连接开销等)平均约为70ms。
为了进一步说明这一点,如果我在存储过程中连续插入多个插入:
DELIMITER $$
CREATE PROCEDURE testInsert(IN input INT)
BEGIN
INSERT INTO test_table(column_1, column_2)
VALUES(input, input);
INSERT INTO test_table(column_1, column_2)
VALUES(input, input);
INSERT INTO test_table(column_1, column_2)
VALUES(input, input);
INSERT INTO test_table(column_1, column_2)
VALUES(input, input);
INSERT INTO test_table(column_1, column_2)
VALUES(input, input);
END$$
DELIMITER ;
从 SQLyog 调用仍然很快:
Execution Time : 0.040 sec
Transfer Time : 0.003 sec
Total Time : 0.044 sec
---------------------------------------------------
调用上面相同的 java 代码现在平均每个过程调用需要225 毫秒。
我希望我做错了一些微不足道的事情,但我愿意接受任何我应该测试的建议或事情。或者从java调用时是否有那么多额外的开销?
抱歉,这篇文章有点长,但我试图提供大量信息。谢谢你的帮助!
更新只是另一种情况,如果我将五个插入移动到一行中:
DELIMITER $$
CREATE PROCEDURE testInsert(IN input INT)
BEGIN
INSERT INTO test_table(column_1, column_2)
VALUES(input, input),(input, input),(input, input),(input, input),(input, input);
END$$
DELIMITER ;
java 运行时平均为80 毫秒,这表明从 java 调用过程中的每个单独语句似乎都有一些额外的开销。
调用没有插入的其他过程,即使是那些更复杂并返回几个不同结果集的过程,所花费的时间也比一些简单的插入要少得多。只有选择的过程返回得很快,但是在过程中添加了一个插入,并且运行时比预期的要慢得多(同样,只是来自 java - 而不是来自 SQLyog)。