我有一个需要运行每日脚本的应用程序;每日脚本包括下载包含1,000,000行的CSV文件,并将这些行插入表中。
我在Dreamhost中托管我的应用程序。我创建了一个遍历所有CSV行的while循环,并为每个行执行INSERT查询。问题是我得到了“500内部服务器错误”。即使我把它分成1000个文件,每个1000行,我也不能在同一个循环中插入超过40或5万行。
有什么方法可以优化输入?我也在考虑使用专用服务器;你觉得怎么样?
谢谢!
佩德罗
答案 0 :(得分:13)
大多数数据库都有优化的批量插入流程 - MySQL's is the LOAD DATA FILE syntax。
要加载CSV文件,请使用:
LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES;
答案 1 :(得分:6)
插入多个值,而不是执行
insert into table values(1,2);
做
insert into table values (1,2),(2,3),(4,5);
一次最多适当的行数。
或批量导入,这是加载数据的最有效方式,请参阅
答案 2 :(得分:3)
通常我会说只使用LOAD DATA INFILE,但似乎你无法使用共享托管环境。
我在几年内没有使用MySQL,但他们有一个非常好的文档,描述了如何加快批量插入的插入: http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html
可以从中收集一些想法:
禁用/启用插入的键:
ALTER TABLE tbl_name DISABLE KEYS; ALTER TABLE tbl_name ENABLE KEYS;
在插入语句中使用多个值。
I.e。:INSERT INTO表(col1,col2)VALUES(val1,val2),(..,..),...
如果我没记错的话,每个插入语句最多可以有4096个值。
在启动之前运行FLUSH TABLES命令,以确保没有可能影响插入性能的待处理磁盘写入。
我认为这会让事情变得更快。我建议使用LOCK TABLES,但我认为禁用密钥会让事情变得毫无意义。
<强>更新强>
我在阅读本文后意识到,通过禁用您的密钥,您可以删除对您的文件加载很重要的一致性检查。您可以通过以下方式解决此问题:
答案 3 :(得分:0)
您可以创建cronjob脚本,该脚本可以在一次请求时将x记录添加到数据库中。 Cronjob脚本将检查上次导入是否还没有添加所有需要的行,他需要另外x行。
因此,您可以添加所需数量的行。
如果您拥有专用服务器,则更容易。您只需使用所有插入查询运行循环。
当然你可以尝试将time_limit设置为0(如果它在dreamhost上工作)或者将它设置得更大。
答案 4 :(得分:0)
您的PHP脚本很可能因超出脚本时间限制而被终止。由于你是在一个共享主机上,你几乎没有运气。
如果切换到专用服务器并且获得shell访问权限,最好的方法是使用mysql命令行工具插入数据。
答案 5 :(得分:0)
OMG小马的建议很棒,但我也“手动”将数据格式化为mysqldump使用的相同格式,然后以这种方式加载。很快。
答案 6 :(得分:0)
BEGIN
发送给MySQL,然后执行所有插入操作COMMIT
。这会显着加快速度,但像卡萨布兰卡所说的那样,你的剧本也可能会超时。
答案 7 :(得分:0)
我以前自己遇到过这个问题,而且几乎没有把它弄好,但是你需要多做一点才能让它发挥最佳效果。
我发现在我的情况下我不能接受一个大的INSERT语句,但发现如果我将它分成大约10k个INSERTS的组,就像nos建议那样它会做它的工作很快。需要注意的一点是,当执行这样的多个INSERT时,您很可能会达到PHP的超时限制,但是通过使用 set_time_limit($ seconds)重置时间可以避免这种情况,我发现这样做在每次成功的INSERT工作之后都很好。
你必须要小心这样做,因为你可能会发现你自己处于一个无限时间的事故循环中,为此我建议通过检查MySQL报告的错误来确保每个INSERT成功。 mysql_errno()或 mysql_error()。您还可以通过使用 mysql_affected_rows()检查受INSERT影响的行数来捕获错误。然后,您可以在第一次错误发生后停止。
答案 8 :(得分:0)
如果你使用sqlloader会更好。 您需要两个第一个控制文件来指定SQL Loader应该执行的操作以及要加载的第二个csv文件 以下链接可以帮助您。 http://www.oracle-dba-online.com/sql_loader.htm
答案 9 :(得分:0)
转到phpmyadmin并选择要插入的表格。
在“操作”选项卡下,然后在“表选项”选项/部分下,将存储引擎从InnoDB更改为MyISAM。
我曾经遇到过类似的挑战。 玩得开心。