【问题标题】:Insert large Excel file into database将大型 Excel 文件插入数据库
【发布时间】:2018-12-31 22:51:10
【问题描述】:

我正在使用Spout 读取超过 500.000 条记录的 Excel 文件(每列有 7 列,信息不多)。

问题是我的脚本超时了。 我已经尝试上传这个限制并且它变得更好了,但到目前为止我无法进行完整的插入,只有部分插入大约 50.000 行。

这不是我的选择。 有什么方法可以拆分这个 Excel 文件,但在代码上? 我看到的是即使文件没有插入数据库,操作文件也已经很慢并且超时了。

那么……有什么建议吗?

谢谢!

【问题讨论】:

  • 您可以分块读取文件。使用范围读取一些行,插入它们,然后使用下一个块再次运行
  • 嗨@LelioFaieta 我已经尝试过,但似乎不知道如何使用Spout。我之前使用过 PHPExcel,它有这个选项,但阅读它处理大文件真的很慢。而且这个真的很大,而且还会继续增长。
  • 我不知道 spout,你也没有分享任何代码。使用 Phpexcel 很容易做到
  • 是在上传失败还是在处理 50,000 行到数据库时失败

标签: php mysql excel bulk-load spout


【解决方案1】:

您可以尝试反复调用set_time_limit(),例如在插入每一行之后。每次调用它都会重置时间限制。但是,如果您的服务器管理员设置了全局时间限制,则不允许您超过该时间限制。

但是在 MySQL 中将 50 万行一一插入到 InnoDB 表中本来就很慢,因为它需要在每一行之后进行自动提交。

如果您分批进行插入,您将获得很大的速度。例如,您现在可能正在做这样的事情:

  INSERT INTO table (col1, col2, col3) VALUES (1, 'baker', 'charlie');
  INSERT INTO table (col1, col2, col3) VALUES (2, 'delta', 'echo');
  INSERT INTO table (col1, col2, col3) VALUES (3, 'foxtrot', 'golf');
  INSERT INTO table (col1, col2, col3) VALUES (4, 'hotel', 'india');
  INSERT INTO table (col1, col2, col3) VALUES (5, 'lima', 'mike');

改为这样做:

  INSERT INTO table (col1, col2, col3) VALUES 
     (1, 'baker', 'charlie'),
     (2, 'delta', 'echo'),
     (3, 'foxtrot', 'golf'),
     (4, 'hotel', 'india'),
     (5, 'lima', 'mike');

这样,您将在 MySQL 上为每五行而不是每行产生一次提交开销。请注意,您可以将许多行放入单个 INSERT,而不仅仅是五个。 MySQL 对查询长度的唯一限制可以通过SHOW VARIABLES LIKE 'max_allowed_packet'; 找到。

当然,这对编程有点复杂,但它要快得多

【讨论】:

    【解决方案2】:

    无论如何,读取包含 3,500,000 个单元格的文件都不会很快。如果在功能强大的硬件上运行并且 Excel 文件使用内联字符串,则至少需要一分钟。

    以下是您的选择:

    1. 如果您控制正在阅读的 Excel 文件的创建,请确保它使用内联字符串(如果您使用 Spout,这是默认行为)。这将大大加快阅读速度。即使您只阅读前两行,您提到的缓慢也是由于这个原因。当不使用内联字符串时,Spout 需要首先预处理包含单元格值的文件,因为它们在另一个地方被引用。使用内联字符串,Spout 可以跳过这个昂贵的步骤并进行真正的流式传输。
    2. 增加时间限制设置,为您的脚本留出更多时间来完成其处理 (set_time_limit)
    3. 批量插入数据库:您应该将它们插入 1000 x 1000(或更多),而不是一一插入。与数据库的每次连接都需要一些时间,因此限制它们是个好主意。

    拆分文件可能有效,但需要提前完成(不在同一个脚本中,否则只会增加总处理时间的时间......)。

    希望有帮助!

    【讨论】:

      【解决方案3】:

      最好的方法是通过这些步骤在后台执行这项工作:

      1. 将 Excel 文件上传到服务器。更新导入作业表 状态:0:等待中
      2. 设置并运行 crob 作业以检查此表并在存在状态为 0 的字段时执行导入作业。更新状态 到 1:处理。执行导入作业服务(批量导入将 是很好的解决方案)。 3. 将状态更新为 2. 如果导入成功完成。
      3. 如果出错...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-26
        相关资源
        最近更新 更多