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 ;
コマンドラインまたはmysqlIDE(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");
}
更新の実行時間(実際の実行のタイミングを計っているだけなので、接続のオーバーヘッドなどは考慮されていないことに注意してください)は、平均で約70ミリ秒です。
ポイントをさらに詳しく説明するために、ストアドプロシージャに複数の挿入を続けて配置すると、次のようになります。
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から呼び出すときに、それだけの余分なオーバーヘッドがありますか?
少し長い投稿で申し訳ありませんが、私はまともな量の情報を提供しようとしていました。助けてくれてありがとう!
更新5つのインサートを1行に移動した場合、追加の状況になります。
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から呼び出されたときに余分なオーバーヘッドがあるように見えることを示しています。
挿入のない他のプロシージャを呼び出すことは、より複雑でいくつかの異なる結果セットを返すものでさえ、いくつかの単純な挿入よりも大幅に短い時間で済みます。selectのみを使用するプロシージャは非常に迅速に戻りますが、プロシージャに挿入を追加すると、実行時間が予想よりもはるかに遅くなります(ここでも、JavaからだけでSQLyogからではありません)。