0

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からではありません)。

4

2 に答える 2

1

代わりに JDBC 接続プールを使用してみて、タイムスタンプを確認してください。(MySQL 挿入と同じではありませんが) 低いはずです。また、MySQL への挿入に使用されているデータ型と、何らかの方法で最適化できるかどうかも確認してください。

于 2012-07-26T03:36:33.963 に答える
0

OK - 何時間も経った後、テーブルのエンジンを InnoDB から MyISAM に変更しようと無作為に決めました。これにより、挿入が大幅に高速化されたようです。

MyISAM での FK とトランザクションの欠如を除いて、2 つのエンジンの違いについてさらに検討する必要があると思います。

少なくとも進歩です。

于 2012-07-26T05:29:33.037 に答える