我想阅读biiiiig CSV-Files并希望将它们插入数据库。这已经奏效了:
if(($handleF = fopen($path."\\".$file, 'r')) !== false){
$i = 1;
// loop through the file line-by-line
while(($dataRow = fgetcsv($handleF,0,";")) !== false) {
// Only start at the startRow, otherwise skip the row.
if($i >= $startRow){
// Check if to use headers
if($lookAtHeaders == 1 && $i == $startRow){
$this->createUberschriften( array_map(array($this, "convert"), $dataRow ) );
} else {
$dataRow = array_map(array($this, "convert"), $dataRow );
$data = $this->changeMapping($dataRow, $startCol);
$this->executeInsert($data, $tableFields);
}
unset($dataRow);
}
$i++;
}
fclose($handleF);
}
我的解决方案的问题是,它非常慢。但是这些文件太大了,无法将其直接放入内存中...所以我想知道,如果有一个可读性,例如10行,则不仅仅是一个或全部读入$ dataRow数组。 我希望在内存和性能之间取得更好的平衡。
你明白我的意思吗?谢谢你的帮助。
格尔茨
V
修改 好的,我仍然需要尝试使用MSSQL-Database找到解决方案。我的解决方案是堆叠数据而不是制作多个MSSQL-Insert:
while(($dataRow = fgetcsv($handleF,0,";")) !== false) {
// Only start at the startRow, otherwise skip the row.
if($i >= $startRow){
// Check if to use headers
if($lookAtHeaders == 1 && $i == $startRow){
$this->createUberschriften( array_map(array($this, "convert"), $dataRow ) );
} else {
$dataRow = array_map(array($this, "convert"), $dataRow );
$data = $this->changeMapping($dataRow, $startCol);
$this->setCurrentRow($i);
if(count($dataStack) > 210){
array_push($dataStack, $data);
#echo '<pre>', print_r($dataStack), '</pre>';
$this->executeInsert($dataStack, $tableFields, true);
// reset the stack
unset($dataStack);
$dataStack = array();
} else {
array_push($dataStack, $data);
}
unset($data);
}
$i++;
unset($dataRow);
}
}
最后我必须循环堆栈并在方法“executeInsert”中构建多个Insert,以创建这样的查询:
INSERT INTO [myTable] (field1, field2) VALUES ('data1', 'data2'),('data2', 'datta3')...
效果更好。我仍然需要检查最佳平衡,但是因此我只能在上面的代码中更改值'210'。我希望帮助每个人都有类似的问题。 注意:在读取完整文件后不要忘记再次执行方法“executeInsert”,因为可能会发生堆栈中仍有一些数据,并且只有当堆栈大小达到210时才会执行该方法。 ..
格尔茨
V
答案 0 :(得分:0)
我认为你的瓶颈不是读取文件。这是一个文本文件。您的瓶颈是SQL表中的INSERT。
执行某些操作,只需注释实际执行插入的行,您就会看到差异。
过去我遇到同样的问题,我完全按照你的意思行事。读取500万行CSV并将其插入Mysql表中。执行时间是60小时 不现实的。
我的解决方案是转向另一种数据库技术。我选择了MongoDB和执行时间 减少到5分钟。 MongoDB 在这种情况下执行速度非常快,并且还有一个名为 mongoimport 的工具,允许您从命令行中直接导入csv文件。
如果db技术不是您的限制,请试一试。
另一种解决方案是将巨大的CSV文件拆分成块,然后多次并行运行相同的php脚本,每个脚本都会处理文件名中带有特定前缀或后缀的块。
我不知道您使用的是哪种特定操作系统,但在Unix / Linux中有一个命令行工具 调用split会为你做这件事,并且还会将你想要的任何前缀或后缀添加到块的文件名中。