【问题标题】:Parsing and Inserting 10 million records into SQL将 1000 万条记录解析并插入 SQL
【发布时间】:2011-09-21 10:55:54
【问题描述】:

所以我在一个 Excel 文件中有大约 1000 万条记录,这些记录必须以特定方式解析(我不能只是转换为 CSV 并像那样插入它)并插入到 mysql 数据库的不同表中。我已经从花了一整夜减少到只花几个小时。但是我想进一步减少这个。有人有任何可以帮助我的技巧或提示吗?我正在使用 Java 和 JDBC 来解析和连接。

【问题讨论】:

  • 你怎么能把它缩短到几个小时?
  • 我的代码有很多低效之处。比如多次打开和关闭一个连接,所以我把它删掉了。我现在只打开一个持久连接。同样在我的原始代码中,我首先加载了所有数据,然后一次处理所有数据,将所有内容保存在内存中。现在我将它加载为 3 个块并一次处理每个块,从而在每个块完成后释放内存。我也有一些统计数据,我正在计算困难,所以我用一些哈希图清理了这些数据。可能还有其他东西,但我现在没有代码。
  • 如果打算将同一个 excel 文件中的数据插入到不同的表中,我建议编写自己的脚本以从 excel 文件中读取并为相应的表生成 INSERT 语句,然后可以批量导入。或者,您的脚本可以直接将数据推送到数据库中。解决方案取决于此导入是一次性活动还是经常性

标签: java mysql optimization jdbc


【解决方案1】:

一个想法...

在 mysql 中创建一个暂存(临时)数据库,其中包含一个名为 excel_staging 的表,该表与您的 excel 文件的结构相匹配 - 为该表使用 myisam 引擎。

使用 load data infile 将 excel 文件(另存为 csv)加载到 excel_staging 表中 - 填充时间不会超过几分钟,尤其是因为它是 myisam。

truncate table excel_staging;

load data infile 'excel_staging.csv'
into table excel_staging
fields terminated by...
lines terminated by..
(
field1,
field2,
...
);

将大量 select 写入 outfile 语句,将 excel_staging 表中的数据提取到单独的 csv 文件中,您将使用这些文件将其加载到您的各个 innodb 生产数据库表中。如有必要,您可以在这一点上发挥真正的创造力 - 您甚至可能需要加载额外的数据来支持连接等,以便生成格式良好的 csv 输出。

select distinct cust_id, name into outfile 'customers.csv' 
fields termniated by...
lines terminated by...
from
 excel_staging
order by
 cust_id; -- order for innodb import

select distinct dept_id, name into outfile 'departments.csv' 
fields termniated by...
lines terminated by...
from
 excel_staging
order by
 dept_id;

使用 load data infile 将格式化、清理和排序的主键 csv 文件加载到您的生产 innodb 表中...

load data infile 'customers.csv'
into table customers
fields terminated by...
lines terminated by..
(
cust_id,
name
);

...

排除编写解决方案的时间(例如 30 分钟)应该能够在大约 ermm 内加载到暂存、输出到 csv 并加载到生产表中……端到端 6 分钟。

希望这会有所帮助。

【讨论】:

  • 我喜欢这个主意,我可以试试。
【解决方案2】:

一些 JDBC 性能提示,将连接对象的 autoCommit 设置为 false。但请确保在大量插入(每 100K 或更多)之后提交。此外,在普通 Statement 对象上使用和重用 PreparedStatement 对象。

【讨论】:

    【解决方案3】:

    Mysql 允许你load from a file。也许你应该做的是:读取 10000 条记录并创建一个文件。在开始读取接下来的 10000 条记录时,开始并行运行 load data infile

    所以这应该让您更接近快速解决方案:

    1. 并行读取和加载
    2. 不要单独插入,而是使用批量数据加载工具

    【讨论】:

    • 我对几个文件(与 fk 相关的 400k 和 ~1.300k)做了同样的事情,加载需要几十秒(通过 JDBC / JPA 使用时需要几十分钟)。跨度>
    • 如果可以在LOAD DATA INFILE之前按主键对数据进行排序,也会更快。
    【解决方案4】:

    确保在插入时禁用外键检查(仅影响 InnoDB),这样可以大大加快速度。完成后当然要重新启用外键。

    【讨论】:

      【解决方案5】:

      考虑使用 executeBatch 并执行 1000 个左右的块。这会有很大帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-12
        • 2012-05-30
        • 2018-02-08
        • 1970-01-01
        • 1970-01-01
        • 2023-01-31
        • 1970-01-01
        相关资源
        最近更新 更多