存储过程中的Mysql插入比Java JDBC慢

时间:2012-07-26 03:10:34

标签: java mysql stored-procedures jdbc mysql-connector

与通过IDE或mysql命令行调用相比,我看到mysql插入时间在通过JDBC调用时执行的速度要慢一些,并且想知道是否有人能指出我正确的方向。

我在本地运行所有内容,因此网络延迟不应成为问题。

我创建了以下非常人为的例子来说明这一点。

我创建了一个存储过程,它接受一个I​​NT并将其插入表中:

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代码,每个过程调用平均 225ms

我希望我做错了一些微不足道的事情,但我愿意接受我应该测试的任何建议或事情。或者从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运行时平均 80ms ,这表明当从java调用时,过程中的每个单独语句似乎都有一些额外的开销。

调用其他没有插入的过程,即使那些更复杂并返回多个不同结果集的过程所花费的时间也比一些简单插入要少得多。只有选择的过程返回非常快,但是在过程中添加了一个插入,并且运行时比预期慢得多(再次,仅来自java - 而不是来自SQLyog)。

2 个答案:

答案 0 :(得分:1)

尝试使用JDBC连接池并检查时间戳 - 它应该更低(尽管与MySQL插入不同)。 还要检查用于插入MySQL的数据类型以及是否可以某种方式对其进行优化。

答案 1 :(得分:0)

好的 - 经过几个小时后,我随机决定尝试将桌面上的引擎从InnoDB更改为MyISAM,这似乎显着加快了插入速度。

猜猜我将不得不对两个引擎之间的差异进行更多的审查,除了在MyISAM中缺少FK和交易。

至少它是进步。