我正在尝试将csv文件导入到mysql表中,我目前有一个逐行运行的脚本,因为我需要将一个id与另一个id结合使用以及格式化mysql格式的日期。
csv文件的列数多于我当前导入的列数。是否更容易导入所有列?
我正在阅读LOAD DATA INFILE(http://dev.mysql.com/doc/refman/5.1/en/load-data.html),但我想知道如何使用它并散列ID和格式化日期而不逐行执行。我当前的脚本占用时间太长,导致运行时出现站点性能问题。
这就是我所拥有的:
$url = 'http://www.example.com/directory/file.csv';
if (($handle = fopen($url, "r")) !== FALSE)
{
fgetcsv($handle, 1000, ",");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$EvID = $data[0];
$Ev = $data[1];
$PerID = $data[2];
$Per = $data[3];
$VName = $data[4];
$VID = $data[5];
$VSA = $data[6];
$DateTime = $data[7];
$PCatID = $data[8];
$PCat = $data[9];
$CCatID = $data[10];
$CCat = $data[11];
$GCatID = $data[12];
$GCat = $data[13];
$City = $data[14];
$State = $data[15];
$StateID = $data[16];
$Country = $data[17];
$CountryID = $data[18];
$Zip = $data[19];
$TYN = $data[20];
$IMAGEURL = $data[21];
$URLLink = $data[22];
$data[7] = strtotime($data[7]);
$data[7] = date("Y-m-d H:i:s",$data[7]);
if((($PCatID == '2') && (($CountryID == '217') or ($CountryID == '38'))) || (($GCatID == '16') or ($GCatID == '19') or ($GCatID == '30') or ($GCatID == '32')))
{
if(!mysql_query("INSERT IGNORE INTO TNDB_CSV2
(id, EvID, Event, PerID, Per, VName,
VID, VSA, DateTime, PCatID, PCat,
CCatID, CCat, GCatID, GCat, City,
State, StateID, Country, CountryID, Zip,
TYN, IMAGEURL) VALUES
('".md5($EventID.$PerformerID)."','".addslashes($data[0])."','".addslashes($data[1])."','".addslashes($data[2])."','".addslashes($data[3])."','".addslashes($data[4])."',
'".addslashes($data[5])."','".addslashes($data[6])."','".addslashes($data[7])."','".addslashes($data[8])."','".addslashes($data[9])."',
'".addslashes($data[10])."','".addslashes($data[11])."','".addslashes($data[12])."','".addslashes($data[13])."','".addslashes($data[14])."',
'".addslashes($data[15])."','".addslashes($data[16])."','".addslashes($data[17])."','".addslashes($data[18])."','".addslashes($data[19])."',
'".addslashes($data[20])."','".addslashes($data[21])."')"))
{
exit("<br>" . mysql_error());
}
}
}
fclose($handle);
}
任何帮助总是非常感谢。提前谢谢。
答案 0 :(得分:5)
首先尝试优化您的脚本。首先,除非您没有其他选择,否则在导入时永远不会运行单个查询,网络开销可能是一个杀手。
尝试类似的东西(显然未在SO文本框中进行测试和编码,检查括号是否与e.c.t匹配):
$url = 'http://www.example.com/directory/file.csv';
if (($handle = fopen($url, "r")) !== FALSE)
{
fgetcsv($handle, 1000, ",");
$imports = array();
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$EvID = $data[0];
$Ev = $data[1];
$PerID = $data[2];
$Per = $data[3];
$VName = $data[4];
$VID = $data[5];
$VSA = $data[6];
$DateTime = $data[7];
$PCatID = $data[8];
$PCat = $data[9];
$CCatID = $data[10];
$CCat = $data[11];
$GCatID = $data[12];
$GCat = $data[13];
$City = $data[14];
$State = $data[15];
$StateID = $data[16];
$Country = $data[17];
$CountryID = $data[18];
$Zip = $data[19];
$TYN = $data[20];
$IMAGEURL = $data[21];
$URLLink = $data[22];
$data[7] = strtotime($data[7]);
$data[7] = date("Y-m-d H:i:s",$data[7]);
if((($PCatID == '2') && (($CountryID == '217') or ($CountryID == '38'))) || (($GCatID == '16') or ($GCatID == '19') or ($GCatID == '30') or ($GCatID == '32')))
{
$imports[] = "('".md5($EventID.$PerformerID)."','".addslashes($data[0])."','".addslashes($data[1])."','".addslashes($data[2])."','".addslashes($data[3])."','".addslashes($data[4])."',
'".addslashes($data[5])."','".addslashes($data[6])."','".addslashes($data[7])."','".addslashes($data[8])."','".addslashes($data[9])."',
'".addslashes($data[10])."','".addslashes($data[11])."','".addslashes($data[12])."','".addslashes($data[13])."','".addslashes($data[14])."',
'".addslashes($data[15])."','".addslashes($data[16])."','".addslashes($data[17])."','".addslashes($data[18])."','".addslashes($data[19])."',
'".addslashes($data[20])."','".addslashes($data[21])."')";
}
}
$importarrays = array_chunk($imports, 100);
foreach($importarrays as $arr) {
if(!mysql_query("INSERT IGNORE INTO TNDB_CSV2
(id, EvID, Event, PerID, Per, VName,
VID, VSA, DateTime, PCatID, PCat,
CCatID, CCat, GCatID, GCat, City,
State, StateID, Country, CountryID, Zip,
TYN, IMAGEURL) VALUES ".implode(',', $arr)){
die("error: ".mysql_error());
}
}
fclose($handle);
}
使用array_chunk中的数字,太大,可能会导致查询太长等问题(是的,my.cnf中存在可配置的限制),太小而且不必要的开销。
你也可以放弃使用$ data [x]赋予变量,因为它是一个浪费,因为脚本有多小,只需在你的查询e.c.t中直接使用$ data [x]。 (不会给出很大的改进,但根据你的进口大小,它可以节省一点)。
接下来将使用低优先级插入/更新,请查看此信息以获取更多信息以帮助您入门:How to give priority to certain queries?
毕竟,你可以想到mysql配置优化,但这是一个谷歌解释真的,因为最好的设置是不同的每个人及其独特的情况
编辑:我之前做过的另一件事是,如果您设置了许多导入不需要的密钥,您可以暂时删除这些密钥并在脚本完成了。这也可以带来很好的时间改进,但是当你在实时数据库上工作时,如果沿着这条路走下去,就会有一些陷阱。
答案 1 :(得分:1)
尝试使用implode()功能进行批量插入。有关进一步说明和示例,请参阅此主题insert multiple rows via a php array into mysql
答案 2 :(得分:1)
我使用了这个查询
$sql = "
LOAD DATA LOCAL INFILE 'uploads/{$fileName}'
REPLACE INTO TABLE `order`
FIELDS
TERMINATED BY '\t'
LINES
TERMINATED BY '\r\n'
IGNORE 1 LINES
(product_id, `date`, quantity)
";
它超级快