对于研究项目,我从当地公交公司的GPS系统(通过他们的API)获取数据。我创建了一个php cron作业,每分钟运行一次,以获取车辆,路线ID,位置,目的地等数据。数据不包含每条公交路线的唯一“运行编号”(一个唯一的编号,以便我可以跟踪一条公共汽车在其路线上的进展),所以我创建了自己的车辆ID,目的地和相对时间是否相似,并为其分配唯一的“运行ID”,以便我可以跟踪它的公共汽车路线。如果不存在运行ID,则生成随机运行ID。 (在最后一次插入行“timeadded”的2分钟内,任何具有相同“vid”和“pid”的车辆都在同一次运行中,这对我的研究非常重要)
每次cron运行(1分钟)时,大约会有80行添加到数据库中。
最初这项工作会很快完成。但是,现在有超过500,000行,我注意到这项工作可能需要40秒以上。我相信这是因为对于~80行中的每一行,它必须检查整个表(“车辆”)以查看是否存在相同的运行ID,实质上是查询大表并插入行80次。我想获得至少一周的数据(现在是第4天),此时我可以导出数据,擦除所有行,然后重新开始。我的问题是:有什么方法可以重构我的PHP / SQL代码以使流程运行得更快?我使用SQL已经好几年了,所以我确信有一种更巧妙的方式可以插入所有这些数据。
<?php
// Obtain data from XML
$xml = simplexml_load_file("url.xml");
foreach ($xml->vehicle as $vehicle) {
$vid = $vehicle->vid;
$tm = $vehicle->tmstmp;
$dat = substr($vehicle->tmstmp, 0, 8);
$tme = substr($vehicle->tmstmp, 9);
$lat = $vehicle->lat;
$lon = $vehicle->lon;
$hdg = $vehicle->hdg;
$pid = $vehicle->pid;
$rt = $vehicle->rt;
$des = $vehicle->des;
$pdist = $vehicle->pdist;
// Database connection and insert
mysql_connect("redacted", "redacted", "redacted") or die(mysql_error()); mysql_select_db("redacted") or die(mysql_error());
$sql_findsim = "SELECT vid, pid, timeadded, run, rt FROM vehicles WHERE vid=" . mysql_real_escape_string($vid). " AND pid=" . mysql_real_escape_string($pid). " AND rt=" . mysql_real_escape_string($rt). " AND timeadded > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 2 MINUTE);";
$handle = mysql_query($sql_findsim);
$row = mysql_fetch_row($handle);
$runid = $row[3];
if($runid !== null) {
$run = $runid;
} else {
$run = substr(md5(rand()), 0, 30);
}
$sql = "INSERT INTO vehicles (vid, tmstmp, dat, tme, lat, lon, hdg, pid, rt, des, pdist, run) VALUES ($vid,'$tm','$dat','$tme','$lat','$lon',$hdg,$pid,'$rt','$des',$pdist,'$run')";
$result = mysql_query($sql);
mysql_close();
}
&GT;
感谢您帮助重构此代码,以使其更快速有效地运行。
答案 0 :(得分:0)
桌子上有索引吗? (vid,pid,rt,timeadded)上的复合索引将使查询更快,从而避免全表扫描。
create index fastmagic on vehicles (vid,pid,rt,timeadded)
或者,您可以跳过全部选择而只是跳过插入而不指定“运行”随机值。这将使您的cron作业保持“恒定时间”,因为您所做的只是追加新数据。
在您获得一周的数据后,请返回并编写“第二遍”代码以逐步执行每一行(通过添加时间从车辆订单中选择*)。对于每一行,按照您已经完成的方式进行“选择” - 然后“更新”您正在处理的行。
如果你选择备用,你可能需要一个自动增量“id”整数列来使行识别更清晰(如果你还没有)。
答案 1 :(得分:0)
我会建议,
创建一个表作为vehicle_ids(或一些有意义的名称)这些字段。
vid, pid, run, rt
而不是在车辆表中检查vid,你可以检查上面的表格是否为id,如果没有插入(将vid作为自动增量)。
规范化您的牌桌并将车辆索引编入索引