Mysql在存储过程中的插入速度慢于Java JDBC



与从IDE或在mysql命令行上调用相比,通过JDBC调用mysql时,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

但是,如果am从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调用过程中的每个语句时似乎都有一些额外的开销。

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

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

OK-几个小时后,我随机决定尝试将表上的引擎从InnoDB更改为MyISAM,这似乎大大加快了插入速度。

我想我将不得不对这两个引擎之间的差异进行更多的审查,除了MyISAM中缺少FK和事务之外。

至少这是一种进步。

最新更新