37

我一直在导入大型 CSV 数据文件;通常少于 100,000 条记录。我正在使用 PHP 和 MySQL(InnoDB 表)。我需要在 MySQL 之前使用 PHP 来转换一些字段并进行一些文本处理INSERT(下面的代码的一部分process_note_data())。MySQLLOAD DATA是不可行的,所以请不要推荐它。

我最近尝试通过使用 MySQL 事务START TRANSACTION和来提高这个过程的速度COMMIT。性能提升令人惊讶。处理时间减少了 20 倍。因此,20 分钟的处理只需要大约 1 分钟。

问题。

1.) 有谁明白为什么会有这样的性能提升(20 分钟到 1 分钟)?

2.) 我应该关心 100,000 条记录的交易量有多大吗?

3.) 我应该关心事务中的大量插入和/或更新吗?

/*
 * Customer Notes Data:
 * Rows are either a meeting, call or note!
 */
$row = 1;
$data = array();
$fields = array();
$line = '';

$db->query('SET autocommit=0;');
$db->query('START TRANSACTION;');

if (($handle = fopen("modules/".$currentModule."/Data/customernote.csv", "r")) !== FALSE) {
  while (($data = fgetcsv($handle, 4096, ',', '"')) !== FALSE && $row < 999000) {
    //Row 1 - CSV header row with field names
    if ($row == 1) {
      $csv_fields = $data;
    } elseif ($row > 1) {
      $fields = $this->process_note_data($data, $csv_fields, $row);
    }
    $row++;
  } // end while
  fclose($handle);
}

$db->query('COMMIT;');
$db->query('SET autocommit=1;');

注意:文本/字段处理在调用中完成$this->process_note_data(),然后调用另一个具有INSERT语句代码的帮助程序类。我没有足够的空间来包含所有代码。$db->query()是 MySQL 查询的典型数据库对象。

4

2 回答 2

26
  1. 请检查此链接:

    https://dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-transaction-management.html

    如果该事务对数据库进行了修改,则 InnoDB 必须在每次事务提交时将日志刷新到磁盘。当每次更改后都有提交时(与默认的自动提交设置一样),存储设备的 I/O 吞吐量会限制每秒潜在操作的数量。

  2. 大事务可能会影响提交期间的性能(检查上面)

  3. 仅在回滚的情况下,但是可以使用某些设置进行优化(检查链接)

于 2013-02-03T17:47:55.160 回答
22

我自己在 .Net 中的小测试(4 个字段记录):

插入 1 条记录,无事务:60毫秒

插入 1 条记录,使用事务:158毫秒

使用事务插入 200 条记录,每条记录后提交:17778 毫秒

不使用事务插入 200 条记录:4940毫秒

使用事务插入 200 条记录,仅在最后一条记录后提交:4552毫秒

使用事务插入 1000 条记录,仅在最后一条记录后提交:21795毫秒

客户在丹麦,服务器在比利时(Google cloud f1-micro)。

我的意思是把它放在评论中,但格式不好......所以这是我提前道歉;-)

于 2016-01-29T12:33:10.310 回答