我试图将json数据导入mysql.My json文件接近3.7Mb并且有近17k行(测试数据真实数据将近65k行)。但是我的脚本速度非常慢,需要将近8-9分钟。有什么快速的方法可以使用php进程界面将json数据导入mysql吗? 我现在试图添加进度条功能及其功能。
$veri=json_decode(file_get_contents('auctions.json'));
$sayi=count($veri->alliance->auctions);
$a=$veri->alliance->auctions;
$yuzde=round($sayi/100);
echo "<div id='tasiyici'>";
$sql=$db->prepare("INSERT INTO auctions (id, auc, item, owner, bid, buyout, quantity, timeLeft) VALUES ('',?,?,?,?,?,?,?)");
for ($i=0;$i<=$sayi;$i++){
$sql->execute(array($a[$i]->auc,$a[$i]->item,$a[$i]->owner,$a[$i]->bid,$a[$i]->buyout,$a[$i]->quantity,$a[$i]->timeLeft));
if($i%$yuzde=='0'){
$y=$i/$yuzde;
if(($y*4+4)>"180"){$pos=40-(($y*4+4)-180); $color="color:#fff";}
if(($y*4+4)>=220){$pos=0;}
echo "<div class='rakam' style='background-position:-".$pos."px 0;".$color."'>%".($y+1)."</div>";
echo "<div class='yuzde' style='width:".($y*4+4)."px;'></div>";
ob_flush();
flush();
}
}
echo "</div>";
echo "<br> $sayi data added.";
CSS代码
<style>
body {
font-family:Arial;
}
#tasiyici {
width:400px;
height:17px;
display: block;
position: relative;
margin:50px auto;
background:#e3e3e3;
border-radius:5px;
overflow: hidden;
border:1px solid #ccc;
}
.yuzde {
height:17px;
display: block;
width:1px;
background:url("progressOverlay.png");
position: absolute;
top:0;
left:0;
z-index:1;
}
.rakam {
width:40px;
height:16px;
display: block;
line-height:17px;
position: absolute;
left:50%;
top:0;
margin-left:-20px;
z-index:9999;
background:url("progressOverlay.png") -40px 0 #e3e3e3 no-repeat;
font-size:11px;
}
</style>
答案 0 :(得分:1)
9分* 60秒= 540秒
17000/540 =插入时每秒约30.5条记录
因为你没有发布你的服务器配置,加载,ram等,所以我们不能直接把问题放在某一点上。无论如何30.5插入/秒对于严肃的服务器来说并不多。这当然非常可行,因为你的行大小似乎不大。
您需要做的是做一些严肃的测量。例如,缺少内存大小会产生问题。桌面上还有许多昂贵的索引会使插入变得非常困难。
如果你多次这样做(例如通过用户上传),为它创建一个队列可能是明智的,因为它总是需要一些时间。虽然17k插入应该可以在几秒钟内完成,而不是几分钟。
有很多关于优化MySQL插入的文档,这是对速度影响的一般概述:http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html
乍一看它似乎不是你的剧本,这并不是特别的。虽然我会用2个脚本分开这个过程:
每个x记录你都可以这样做:
UPDATE importjobs SET counter = :amountimported WHERE id=:jobid
一个脚本,让您回答状态。通过获取后台脚本写入的状态消息。
SELECT counter / total AS partdone,counter,total FROM importjobs WHERE id =:jobid
通过这种方式,您可以完全独立于用户界面来衡量和改进流程。关注的分离发生了。您可以全速进行导入,并且可以完全从过程中分离更新指示器。
根据您获得的速度,您可以决定是否要每5,10,20,60秒更新一次。这种查找非常便宜,所以你可以做很多次。主要是因为importjobs表也很小。
答案 1 :(得分:1)
我有一个类似的问题要解决,但我不知道外部API的记录数量。我意识到我的工作可能会在中期过程中失败而且我不想再重新开始。
令我感到震惊的是,你的问题在这方面是类似的。您要求数据库执行的操作是尝试插入记录,即使记录已存在也是如此。这很昂贵。
我所做的是构建一个存储数据密钥或一些唯一标识符的控制表。在处理期间,作业读取控制数据库以确定记录是否存在,如果存在,则跳到下一个记录,否则插入它。
我创建了一个记录编号限制器,我可以测试负载(比如限制前100条记录),使用这个工具,我能够在浏览器的5个打开标签中运行php脚本,以有效地创建并行加载。
答案 2 :(得分:0)
如果扩展插入仍然不够快,请尝试使用load data infile。它不会给你进步,但它会以我所知的最快的速度加载你的数据。
编辑这是mysql手册页http://dev.mysql.com/doc/refman/5.1/en/load-data.html的链接