批量更新到MySQL中的临时表的插入速度不一致(使用jdbcTemplate.batchUpdate)

时间:2016-01-14 11:46:38

标签: mysql performance mariadb

我有MariaDb实例和临时表。工作流程:

  1. 开始交易
  2. 如果存在则删除临时表,创建临时表
  3. 使用insert into TEMP1 (xxx,yyy) values(?,?),(?,?),(?,?),(?,?)...
  4. 向其插入40K记录
  5. 以某种方式处理此数据
  6. 结束交易
  7. Worflow在一个线程中执行。 问题定义:首次运行此工作流程在1-3秒内插入40K记录,所有连续运行在30-40秒内插入40K。

    任何人都可以告诉如何让它在所有运行中运行1-3秒吗?

    表格定义:

    CREATE TEMPORARY TABLE IF NOT EXISTS TEMP1 (
    uuid varchar(80) COLLATE utf8_unicode_ci NOT NULL,
    raw_content longtext COLLATE utf8_unicode_ci NOT NULL,
    security_level varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    key_name varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    stage_user_uuid varchar(80) NOT NULL,
    data_type varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    string_value varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
    integer_value bigint(20) DEFAULT NULL,
    double_value double DEFAULT NULL,
    date_value datetime DEFAULT NULL, 
    INDEX user_uuid_idx (stage_user_uuid)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    

2 个答案:

答案 0 :(得分:1)

问题是我用jdbcTemplate.batchUpdate以一种非常奇怪的方式工作。我设置了rewriteBatchedStatements=true

第一次运行真正执行过的声明

insert into TEMP1 (xxx,yyy) values(?,?),(?,?),(?,?),(?,?);

未知原因的下一个语句逐个执行语句

insert into TEMP1 (xxx,yyy) values(?,?);
insert into TEMP1 (xxx,yyy) values(?,?);
insert into TEMP1 (xxx,yyy) values(?,?);

这导致了缓慢。

在具有此后缀的日志中可以看到实际语句到连接字符串:&logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true

我最终定期准备好批处理语句,并且完美无缺。

ps.addBatch()
ps.executeBatch()
ps.clearBatch()

问题的根源是jdbcTemplate.batchUpdate使用JdbcUtils.supportsBatchUpdates因某些原因失败。我使用org.apache.tomcat:tomcat-jdbc:8.0.30 pool

driver 'supportsBatchUpdates' method threw exception
java.sql.SQLException: PooledConnection has already been closed.
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:87)
    at com.sun.proxy.$Proxy37.getMetaData(Unknown Source)
    at org.springframework.jdbc.support.JdbcUtils.supportsBatchUpdates(JdbcUtils.java:359)
    at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:897)
    at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:890)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
    at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:890)

答案 1 :(得分:-1)

表上的索引数是插入性能的最主要因素。表具有的索引越多,执行就越慢。 insert语句是唯一不能直接从索引中获益的操作,因为它没有where子句。

如果表上有索引,则数据库必须确保通过这些索引找到新条目。因此,它必须将新条目添加到该表的每个索引。因此,索引的数量是insert语句的成本的乘数。

为了优化插入性能,保持索引数量很小非常重要。

了解更多here