简体   繁体   中英

Mysql inserts in stored procedure slow over Java JDBC

I am seeing mysql insert times performing orders of magnitude slower when called over JDBC when compared to calling from an IDE or on the mysql command line and was wondering if anyone could point me in the right direction.

I am running everything locally, so network latency should not be an issue.

I created the following very contrived example to illustrate the point.

I created a stored procedure that takes in a single INT and inserts it into a table:

DELIMITER $$

CREATE PROCEDURE testInsert(IN input INT)
BEGIN
        INSERT INTO test_table(column_1, column_2) 
        VALUES(input, input);

    END$$

DELIMITER ;

If I were to call this procedure from the command line or a mysql IDE (I am using SQLyog):

CALL testInsert(0);

The procedure call happens, for all intents and purposes, instantly:

Execution Time : 0.007 sec
Transfer Time  : 0.001 sec
Total Time     : 0.009 sec

However if am to call the procedure from Java, using the following code:

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");
}

The runtime of the update (note that I am only timing the actual execution so connection overhead and etc are not being taken into account) averages to be about . )(请注意,我只是在计时实际的执行时间,因此不考虑连接开销等)。

To even further illustration the point, if I put several inserts in a row into the stored procedure:

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 ;

Calling from SQLyog still quite quick:

Execution Time : 0.040 sec
Transfer Time  : 0.003 sec
Total Time     : 0.044 sec
---------------------------------------------------

Calling the same java code above now averages per procedure call.

I am hoping that there is some trivial thing I am doing wrong, but am open to any suggestions or things that I should test. Or is there just that much extra overhead when calling from java?

Sorry for the somewhat long post but I was trying to provide a decent amount of information. Thanks for any help!

Just an additional situation, if I move the five inserts into a single line: 如果将五个插入物移动到一行中,则是另外一种情况:

 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 ;

The java runtime is averaging which shows that each individual statement in the procedure seems to have some extra overhead when being called from java. ,这表明从Java调用过程中的每个语句似乎都有一些额外的开销。

Calling other procedures that have no inserts, even those that are more complicated and return several different result sets are taking significantly less time than some simple inserts. Procedures with only selects return very quickly, but add an insert into the procedure though and the runtime is much slower than expected (again, just from java - not from an SQLyog).

try using a JDBC connection pool instead and check the timestamps - it should be lower (though not the same as the MySQL insert). Also check the data types being used for the insert into MySQL and whether that can be optimized somehow.

OK - after many hours I randomly decided to try to change engine on the table from InnoDB to MyISAM and this seemed to speed up inserts significantly.

Guess I will have to do more review on the differences between the two engines, other than lack of FKs and transactions in MyISAM.

At least it is progress.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM