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 ;

如果我要从命令行或 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 代码现在平均每个过程调用需要225 毫秒。

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

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

4

2 回答 2

1

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

于 2012-07-26T03:36:33.963 回答
0

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

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

至少这是进步。

于 2012-07-26T05:29:33.037 回答