代码之家  ›  专栏  ›  技术社区  ›  Adam

与SQL Server相比,MariaDB JDBC驱动程序无法有效地批处理更新

  •  0
  • Adam  · 技术社区  · 7 年前

    我对我的应用程序中的insert/update/delete例程的性能进行了基准测试,该例程将从sqlserver移植到MariaDB。

    • JDBC公司网址:mariadb.jdbc:mariadb java公司-客户:2.2.4
    • 10.2.12-MariaDB-log AWS上的MariaDB服务器

    基准测试触发50000个插入,同样的更新和删除。

    带有MariaDB java客户机驱动程序的MariaDB执行插入更快,但是更新(和删除)要慢得多,只有3.5秒。

    我尝试了多种JDBC连接字符串的变体,结果是最快的:

      ?verifyServerCertificate=true\
      &useSSL=true\
      &requireSSL=true\
      &allowMultiQueries=true\
      &cachePrepStmts=true\
      &cacheResultSetMetadata=true\
      &cacheServerConfiguration=true\
      &elideSetAutoCommits=true\
      &maintainTimeStats=false\
      &prepStmtCacheSize=50000\
      &prepStmtCacheSqlLimit=204800\
      &rewriteBatchedStatements=false\
      &useBatchMultiSend=true\
      &useBatchMultiSendNumber=50000\
      &useBulkStmts=true\
      &useLocalSessionState=true\
      &useLocalTransactionState=true\
      &useServerPrepStmts=true
    

    在所有情况下,mysql和mysql connectorj的性能都比mariadb差。

    How do I increase the speed of a large series of UPDATEs in mySQL vs SQL Server?

    为了防止可能是服务器配置错误,下面是关键变量:

    key_buffer_size                16MB
    innodb_buffer_pool_size        24GB (mem 30GB)
    innodb_log_file_size           134MB
    innodb_log_buffer_size         8MB
    innodb_flush_log_at_trx_commit 0
    max_allowed_packet             16MB
    

    我的5万次写入数据量很小,大约为2MB。但是对于SQL语法,当它通过JDBC连接时,这个值可能要大10倍——对吗?

    以下是SQL和解释计划:

    Describe `data`
    +---------------+------------------+------+-----+---------------------+-------------------------------+
    | Field         | Type             | Null | Key | Default             | Extra                         |
    +---------------+------------------+------+-----+---------------------+-------------------------------+
    | parentId      | int(10) unsigned | NO   | PRI | NULL                |                               |
    | modifiedDate  | date             | NO   | PRI | NULL                |                               |
    | valueDate     | date             | NO   | PRI | NULL                |                               |
    | value         | float            | NO   |     | NULL                |                               |
    | versionstamp  | int(10) unsigned | NO   |     | 1                   |                               |
    | createdDate   | datetime         | YES  |     | current_timestamp() |                               |
    | last_modified | datetime         | YES  |     | NULL                | on update current_timestamp() |
    +---------------+------------------+------+-----+---------------------+-------------------------------+
    
    INSERT INTO `data` (`value`, `parentId`, `modifiedDate`, `valueDate`) VALUES (4853.16314229298,52054,'20-Apr-18','28-Dec-18')
    
    +------+-------------+-------+------+---------------+------+---------+------+------+-------+
    | id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    +------+-------------+-------+------+---------------+------+---------+------+------+-------+
    |    1 | INSERT      | data  | ALL  | NULL          | NULL | NULL    | NULL | NULL | NULL  |
    +------+-------------+-------+------+---------------+------+---------+------+------+-------+
    
    
    
    UPDATE `data` SET `value` = 4853.16314229298 WHERE `parentId` = 52054 AND `modifiedDate` = '20-Apr-18' AND `valueDate` = '28-Dec-18'
    
    +------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
    | id   | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
    +------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
    |    1 | SIMPLE      | data  | range | PRIMARY       | PRIMARY | 10      | NULL |    1 | Using where |
    +------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
    
    
    DELETE FROM `data` WHERE `parentId` = 52054 AND `modifiedDate` = '20-Apr-18' AND `valueDate` = '29-Jan-16'
    
    +------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
    | id   | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
    +------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
    |    1 | SIMPLE      | data  | range | PRIMARY       | PRIMARY | 10      | NULL |    1 | Using where |
    +------+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
    

    JDBC用法-这是一个精简版,请原谅任何严重错误:

        final Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        try (PreparedStatement statement = connection.prepareStatement(
                     "UPDATE data SET value = ? " +
                             "WHERE parentId = ? " +
                             "AND modifiedDate = ? " +
                             "AND valueDate = ? ")) {
            // timeSeries is a list of 50,000 data points
            Arrays.stream(timeSeries)
                    .forEach(ts -> {
                try {
                    statement.setDouble(1, value);
                    statement.setLong(2, parentId);
                    statement.setDate(3, new java.sql.Date(
                            modifiedDate.getTime()));
                    statement.setDate(4, new java.sql.Date(
                            valueDate.getTime()));
                    statement.addBatch();
                } catch (SQLException e) {
                    throw new RuntimeException(
                            "Bad batch statement handling", e);
                }
            });
            int[] results = statement.executeBatch();
            connection.commit();
        } catch (SQLException e) {
            connection.rollback();
            throw e;
        } finally {
            connection.close();
        }
    

    这是让我惊讶的-似乎没有批处理:

    13/06/2018 15:09    service_user_t[service_user_t] @  [9.177.2.31]  75954   298206495   Query   set autocommit=0
    13/06/2018 15:09    service_user_t[service_user_t] @  [9.177.2.31]  75954   298206495   Prepare UPDATE `data` SET `value` = ? WHERE `parentId` = ? AND `modifiedDate` = ? AND `valueDate` = ?
    13/06/2018 15:09    service_user_t[service_user_t] @  [9.177.2.31]  75954   298206495   Execute UPDATE `data` SET `value` = ? WHERE `parentId` = ? AND `modifiedDate` = ? AND `valueDate` = ?
    13/06/2018 15:09    service_user_t[service_user_t] @  [9.177.2.31]  75954   298206495   Execute UPDATE `data` SET `value` = ? WHERE `parentId` = ? AND `modifiedDate` = ? AND `valueDate` = ?
    13/06/2018 15:09    service_user_t[service_user_t] @  [9.177.2.31]  75954   298206495   Execute UPDATE `data` SET `value` = ? WHERE `parentId` = ? AND `modifiedDate` = ? AND `valueDate` = ?
    13/06/2018 15:09    service_user_t[service_user_t] @  [9.177.2.31]  75954   298206495   Execute UPDATE `data` SET `value` = ? WHERE `parentId` = ? AND `modifiedDate` = ? AND `valueDate` = ?
    13/06/2018 15:09    service_user_t[service_user_t] @  [9.177.2.31]  75954   298206495   Execute UPDATE `data` SET `value` = ? WHERE `parentId` = ? AND `modifiedDate` = ? AND `valueDate` = ?
    etc
    etc
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Vladislav Vaintroub    7 年前

    在批处理中的某些行之间添加“begin”和“commit”语句。 或者在批处理之前启动事务,然后在批处理之后提交。 这比成千上万的个人陈述要快得多。

    如果只执行插入,则rewriteBatchStatements=true将大大加快速度,而不需要事务处理。你也可以把最大包大小增加到1GB,这样可以进行更多的批处理,也许你的整个批处理会被转换成1个非常大的多个插入。