我在尝试将大型CSV文件导入localhost上的mysql时非常麻烦。
CSV大约为55 MB,大约有750,000行。
我重写了脚本,以便解析CSV并逐个转储行。
以下是代码:
$row = 1;
if (($handle = fopen("postal_codes.csv", "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++)
{
$arr = explode('|', $data[$c]);
$postcode = mysql_real_escape_string($arr[1]);
$city_name = mysql_real_escape_string($arr[2]);
$city_slug = mysql_real_escape_string(toAscii($city_name));
$prov_name = mysql_real_escape_string($arr[3]);
$prov_slug = mysql_real_escape_string(toAscii($prov_name));
$prov_abbr = mysql_real_escape_string($arr[4]);
$lat = mysql_real_escape_string($arr[6]);
$lng = mysql_real_escape_string($arr[7]);
mysql_query("insert into cities (`postcode`, `city_name`, `city_slug`, `prov_name`, `prov_slug`, `prov_abbr`, `lat`, `lng`)
values ('$postcode', '$city_name', '$city_slug', '$prov_name', '$prov_slug', '$prov_abbr', '$lat', '$lng')") or die(mysql_error());
}
}
fclose($handle);
}
问题是它需要永远执行。任何熟悉的解决方案都将受到赞赏。
答案 0 :(得分:6)
你正在重新发明轮子。查看MySQL附带的mysqlimport工具。它是导入CSV数据文件的有效工具。
mysqlimport是LOAD DATA LOCAL INFILE
SQL语句的命令行界面。
要么比逐行INSERT快10-20倍。
答案 1 :(得分:2)
您的问题很可能是您自动提交(默认情况下),因此MySQL为每个插入提交了一个新事务。您应该使用SET autocommit=0;
关闭自动提交。如果你可以切换到使用mysqli库(如果可能的话,你可以使用),你可以使用mysqli::autocommit(false)
来关闭自动提交。
$mysqli = new mysqli('localhost','db_user','my_password','mysql');
$mysqli->autocommit(false);
$stmt=$mysqli->prepare("insert into cities (`postcode`, `city_name`, `city_slug`, `prov_name`, `prov_slug`, `prov_abbr`, `lat`, `lng`)
values (?, ?, ?, ?, ?, ?, ?, ?);")
$row = 1;
if (($handle = fopen("postal_codes.csv", "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++)
{
$arr = explode('|', $data[$c]);
$stmt->bind_param('ssssssdd', $arr[1], $arr[2], toAscii(arr[2]), $arr[3], toAscii($arr[3]), $arr[4], $arr[6], $arr[7]);
$stmt->execute();
}
}
}
$mysqli->commit();
fclose($handle);
答案 2 :(得分:2)
如果可以
,使用LOAD DATA要快得多答案 3 :(得分:1)
尝试在一个查询中执行此操作。
虽然
可能会受到my.cnf(mysql配置)的限制<?php
$row = 1;
$query = ("insert into cities ");
if (($handle = fopen("postal_codes.csv", "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++)
{
$arr = explode('|', $data[$c]);
$postcode = mysql_real_escape_string($arr[1]);
$city_name = mysql_real_escape_string($arr[2]);
$city_slug = mysql_real_escape_string(toAscii($city_name));
$prov_name = mysql_real_escape_string($arr[3]);
$prov_slug = mysql_real_escape_string(toAscii($prov_name));
$prov_abbr = mysql_real_escape_string($arr[4]);
$lat = mysql_real_escape_string($arr[6]);
$lng = mysql_real_escape_string($arr[7]);
$query .= "(`postcode`, `city_name`, `city_slug`, `prov_name`, `prov_slug`, `prov_abbr`, `lat`, `lng`)
values ('$postcode', '$city_name', '$city_slug', '$prov_name', '$prov_slug', '$prov_abbr', '$lat', '$lng'),";
}
}
fclose($handle);
}
mysql_query(rtrim($query, ","));
如果它不起作用,你可以尝试这个(禁用自动提交)
mysql_query("SET autocommit = 0");
$row = 1;
if (($handle = fopen("postal_codes.csv", "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++)
{
$arr = explode('|', $data[$c]);
$postcode = mysql_real_escape_string($arr[1]);
$city_name = mysql_real_escape_string($arr[2]);
$city_slug = mysql_real_escape_string(toAscii($city_name));
$prov_name = mysql_real_escape_string($arr[3]);
$prov_slug = mysql_real_escape_string(toAscii($prov_name));
$prov_abbr = mysql_real_escape_string($arr[4]);
$lat = mysql_real_escape_string($arr[6]);
$lng = mysql_real_escape_string($arr[7]);
mysql_query("insert into cities (`postcode`, `city_name`, `city_slug`, `prov_name`, `prov_slug`, `prov_abbr`, `lat`, `lng`)
values ('$postcode', '$city_name', '$city_slug', '$prov_name', '$prov_slug', '$prov_abbr', '$lat', '$lng')") or die(mysql_error());
}
}
fclose($handle);
}
答案 4 :(得分:1)
我使用SQL服务器执行此操作:
答案 5 :(得分:0)
有时当您使用加载数据时,如果有警告,导入将停止。您可以使用关键字ignore。
LOAD DATA INFILE 'file Path' IGNORE INTO TABLE YOUR_Table
答案 6 :(得分:0)
我有类似的情况,使用LOAD DATA是不可行的。交易有时也是不可接受的,因为需要检查重复数据。然而,以下内容大大改善了我的一些导入数据文件的处理时间。
在while循环(CSV Lines)之前,将autocommit设置为0并启动事务(仅限InnoDB):
mysql_query('SET autocommit=0;');
mysql_query('START TRANSACTION;');
循环后,提交并重置自动提交回1(默认值):
mysql_query('COMMIT;');
mysql_query('SET autocommit=1;');
将mysql_query()替换为您的代码使用的任何数据库对象。我希望这有助于其他人。