我一直在处理导入大型CSV数据文件,通常少于10万条记录。使用PHP和MySQL(InnoDB表)。在MySQL的INSERT
操作之前,我需要使用PHP对某些字段进行转换和文本处理(在下面的代码中的process_note_data()
部分)。由于不可行,请不要建议使用MySQL的LOAD 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查询的典型数据库对象。
内存处理
; 提交 ~=刷新到存储器
- जलजनकSET autocommit=0;
,然后再执行相反的操作。请参考官方文档:使用START TRANSACTION
命令后,直到你使用COMMIT
或ROLLBACK
结束事务前,都会保持自动提交禁用状态。 - BlueRaja - Danny Pflughoeft