更好的性能-MySQL临时表或直接读取CSV文件或其他内容?

时间:2018-08-04 03:39:44

标签: php mysql performance

每天,我会得到一个包含25万行40列的csv源文件。 290MB。我将需要对其进行过滤,因为它的行数超过了我的需要,列数也超过了我的需要。

对于每个符合过滤条件的行,我们希望使用其PHP API一次将其更新到目标系统1记录中。

在获得最快性能的API调用(读取/过滤/加载)之前,什么是最好的方法?

  1. 遍历文件的每一行,确定它是否是我想要的行,仅获取我需要的列,然后将其传递给API?

  2. 使用LOAD DATA INFILE将所有记录加载到临时MySQL表中。然后在表中查询所需的行和字段,并遍历结果集以将每条记录传递给API?

还有更好的选择吗?

谢谢!

2 个答案:

答案 0 :(得分:0)

我首先需要做一个假设,大部分25万行将进入数据库。如果百分比很小,那么遍历文件并批量发送所有行肯定会更快。

不同的配置可能会影响这两种方法,但是一般而言,第二种方法的执行效果更好,而脚本编写工作却更少。

方法1:最坏的情况是将每一行发送到服务器。更多往返和更多小的提交。

您可以在此处进行改进的是批量发送行,也许一起发送几百行。您会看到更好的结果。

方法2:由于ACID的所有开销和复杂性,MyISAM将比InnoDB更快。如果您可以接受MyISAM,请先尝试。

对于InnoDB,有一个更好的方法3(实际上是方法1和方法2的混合)。 由于InnoDB不会进行表锁定,因此您可以尝试同时导入多个文件,即将CSV文件分离为多个文件并从脚本中执行加载数据。不要先将auto_increment键添加到表中,以避免auto_inc锁定。

答案 1 :(得分:0)

  1. LOAD DATA,但对不需要保留的列说@dummy1, @dummy2等。这样就消除了多余的列。加载到临时表中。 (1条SQL语句。)
  2. 对数据进行任何清理。 (一些SQL语句,但如果可能,则 no 循环。)
  3. 执行一个INSERT INTO real_table SELECT ... FROM tmp_table WHERE ...来过滤掉不必要的行并将所需的行复制到真实表中。 (1条SQL语句。)

您没有提到步骤2的任何需要。您可能需要一些注意事项:

  • 从其他计算一列。
  • 标准化。
  • 将日期解析为正确的格式。

在一个项目中,我做了:

  • 每小时传送1GB数据。
  • 加载到临时表中。
  • 标准化几列(每列2条SQL)
  • 一些其他处理。
  • 将数据汇总到大约6个汇总表中。样本:INSERT INTO summary SELECT a,b,COUNT(*),SUM(c) FROM tmp GROUP BY a,b;。或使用INSERT ON DUPLICATE KEY UPDATE处理summary中已经存在的行。
  • 最后将经过标准化,清理的数据复制到“真实”表中。
  • 整个过程花了7分钟。

是否使用MyISAM,InnoDB或MEMORY-您需要对自己的案例进行基准测试。由于每个处理步骤都会进行全表扫描,因此tmp表上不需要索引。

因此,每24小时0.3GB-应该不流汗。