首页 > 解决方案 > 使用 JDBC:将数据从 tar.gz 传输到 MySQL db 在大约 200k 个条目后变得缓慢

问题描述

在过去的几天里,我一直在尝试将结构化 (xml) 数据从 tar.gz(约 1.45 万个相当小的不同文件)转换为更友好的格式到数据库中。

我不确定我可能会披露哪些数据或用例,但我会尽力解释我的努力。

我有一个包含以下列类型(MySQL;InnoDB)的表:

int(11) PK NN UQ
varchar(150) NN
varchar(400) NN
text 
text NN
varchar(45) NN UQ
varchar(80) NN
date NN
text 
varchar(300) 
varchar(300) 
varchar(500) 
varchar(260) 
varchar(200) 
varchar(45)

遍历整个 tar 只需查看数据 + 解析大约需要 90 秒 +/-:

try (TarArchiveInputStream tarArchiveInputStream =
                     new TarArchiveInputStream(
                             new BufferedInputStream(
                                     new GzipCompressorInputStream(
                                             new FileInputStream(tarLocation))))){

...
    while ((entry = tarArchiveInputStream.getNextTarEntry()) != null && processedTarEntries < maxNumber) {
    ...PARSING + SOME STATISTICS....
    }
}

我希望以下代码足以深入了解我的迭代过程;如果没有,我将尝试提供更多(本示例中使用 totalCount 来生成人工 id)。准备好的语句是“正常”的 INSERT INTO 语句。

setPreparedStatementValues(preparedStatement, record, totalCount[0]++);

preparedStatement.addBatch();

counter[0]++;

if (counter[0] == BATCH_SIZE){
    counter[0] = 0;
    preparedStatement.executeBatch();
    connection.commit();
    watch.stop();
    System.out.println("Elapsed time for batch " + (totalCount[0] / BATCH_SIZE) + ": " + watch.getTime());
    watch.reset();
    watch.start();
}

sout-output 的相关部分如下(批量大小 5k/10k 并没有真正产生影响):

Elapsed time for batch 29: 3430
Elapsed time for batch 30: 3400
Elapsed time for batch 31: 3553
Elapsed time for batch 32: 3405
Elapsed time for batch 33: 3509
Elapsed time for batch 34: 3544
Elapsed time for batch 35: 6124
Elapsed time for batch 36: 5273
Elapsed time for batch 37: 9171
Elapsed time for batch 38: 8922
Elapsed time for batch 39: 24878
Elapsed time for batch 40: 68124
Elapsed time for batch 41: 70886
Elapsed time for batch 42: 78856
Elapsed time for batch 43: 80879
Elapsed time for batch 44: 85223
Elapsed time for batch 45: 92639
Elapsed time for batch 46: 80106

时间似乎是线性的,直到第 40 批之前的某个地方很短,然后才爆炸。这个输出来自一个最大 300k 条目的实验,但我试图将它分成两个单独的运行,每个运行 150k 条目。输出与尝试一次性完成所有 300k 非常相似。

如果我错了,或者建议如何加快速度,我将非常感谢您提出我可能做错的建议!

标签: javamysqljdbc

解决方案


推荐阅读