我有一个PHP脚本来更新数据库中的数据,从文件名中获取详细信息
<?php
$executionStartTime = microtime(true);
define('DIR_SEARCH', 'FTPSERVERDEV/images/');
$files = glob('FTPSERVERDEV/images/*.*', GLOB_BRACE);
foreach ($files as $filename) {
$files[$filename] = filemtime($filename);
}
arsort($files);
$newest = array_slice($files, 0, 30);
//print_r($newest);
//$file=key($newest);
foreach ($newest as $key=>$value) {
//echo 'key:'.$key.' file name:'.$value.'<br>';
$file_value=end(explode('/', $key));
// echo $file_value.'<br>';
//Targhe MAIN_2FZA4_20170328003752448_VEHICLE_DETECTION
$licenseDetailsEach = explode("_", $file_value);
$cameraName = end(explode('/',$licenseDetailsEach[0]));
$licensePlate = $licenseDetailsEach[1];
$year=substr($licenseDetailsEach[2], 0,4);
$month=substr($licenseDetailsEach[2], 4,2);
$day=substr($licenseDetailsEach[2], 6,2);
$hour = substr($licenseDetailsEach[2], 8,2);
$min = substr($licenseDetailsEach[2], 10,2);
$seconds = substr($licenseDetailsEach[2], 12,2);
$timeRemain = substr($licenseDetailsEach[2], 14,3);
//echo'<br> year:'. $year.'mm:'.$month.'dd:'.$day;
$dateAdded = $year.'-'.$month.'-'.$day;
$timeAdded = $hour.':'.$min.':'.$seconds.' '.$timeRemain;
$time=$hour.':'.$min.':'.$seconds;
$created_at= $dateAdded.' '.$time;
$extention = $licenseDetailsEach[3].'_'.$licenseDetailsEach[4];
$fileName = end(explode('/',$licenseDetailsEach[0]))."_".$licenseDetailsEach[1]."_".$licenseDetailsEach[2]."_".$licenseDetailsEach[3]."_".$licenseDetailsEach[4];
$extra=substr($licenseDetailsEach[2],8);
//echo '<br> cameraName:'.$cameraName.'<br> licensePlate:'.$licensePlate.'<br> dateAdded:'.$dateAdded.' <br>created at:'.$created_at.' <br>extra:'.$extra.'<br> fileName:'.$fileName;
//insert into database with a prepared statement
$con=new PDO("mysql:host=localhost;dbname=lpm;","root","password");
$stmt=$con->prepare('select *from license where(fileName=:fileName)');
$stmt->execute(['fileName'=>$fileName]);
$is_exists=$stmt->rowCount();
if(!$is_exists)
{
$stmt = $con->prepare('INSERT INTO license (fileName,cameraName,licensePlate,dateAdded,extra,created_at) VALUES (:fileName, :cameraName, :licensePlate, :dateAdded, :extra, :created_at)');
$stmt->execute(array(
':fileName' => $fileName,
':cameraName' => $cameraName,
':licensePlate' => $licensePlate,
':dateAdded' => $dateAdded,
':extra' => $extra,
':created_at' => $created_at
));
}
}
$executionEndTime = microtime(true);
//The result will be in seconds and milliseconds.
$seconds = $executionEndTime - $executionStartTime;
echo "This script took $seconds to execute.";
?>现在它可以在5-6秒内更新数据库中的10-15个数据。但FTPSERVER每秒接收4-10个文件。
如何优化或实现这一点?
到底能做到吗?
发布于 2017-06-13 18:17:13
正如@LawrenceCherone所引用的,您应该检查foreach循环中的每一行,并删除在每次迭代中没有更改的所有内容。例如,new PDO将相对昂贵,并且不需要在每个周期中不断创建新的对象。我想单单这一点就会给你带来很大的进步。
您有两个方面的问题;数据库对象在以下位置创建:
$con=new PDO("mysql:host=localhost;dbname=lpm;","root","password");并检查该行是否已存在于:
$stmt=$con->prepare('select *from license where(fileName=:fileName)');顺便说一句,我不熟悉你的方括号语法,它看起来效率很低,而且你在* from之间缺少空格是一个语法错误。
因此,第一部分:只创建一次内容
修复数据库对象创建,使其在页面加载时仅创建一个对象,而不是每次迭代创建一个对象。
$con=new PDO("mysql:host=localhost;dbname=lpm;","root","password");
foreach ($newest as $key=>$value) {
....
}已排序。
第二部分:提高SQL查询的效率
这涉及到删除SELECT/COUNT查询和instead using MySQL unique indexes (amongst other possible ways)以执行类似以下操作:
$stmt = $con->prepare('INSERT IGNORE INTO license
(fileName,cameraName,licensePlate,dateAdded,extra,created_at)
VALUES (:fileName, :cameraName, :licensePlate, :dateAdded,
:extra, :created_at)');如果存在唯一索引重复之类的问题,上面的代码将忽略insert。从您的代码判断,我预计您可能会将fileName表列用作唯一索引,因此请将其设置为:
您可以使用CREATE UNIQUE INDEX fileName ON license添加唯一索引。
我认为,如果您需要非唯一的fileName引用,这可能不是最好的方法,但是referenced source question有几种可能的解决方案,我建议您尝试一下。
第三部分:索引您的SQL!
从第2部分开始,您应该对SQL表进行智能的索引,以便MySQL能够以尽可能最有效的方式检查和返回结果。在这里和across the interwebz上有很多关于这方面的文献。这本书非常值得一读和探索。
示例:
$con=new PDO("mysql:host=localhost;dbname=lpm;","root","password");
foreach ($newest as $key=>$value) {
...
$stmt = $con->prepare('INSERT IGNORE INTO license
(fileName,cameraName,licensePlate,dateAdded,extra,created_at)
VALUES (:fileName, :cameraName, :licensePlate, :dateAdded,
:extra, :created_at)');
$stmt->execute(array(
':fileName' => $fileName,
':cameraName' => $cameraName,
':licensePlate' => $licensePlate,
':dateAdded' => $dateAdded,
':extra' => $extra,
':created_at' => $created_at
));
}发布于 2017-06-13 18:14:05
“优化”这段代码不会对代码的性能、可伸缩性或功能产生重大影响(至少有一个竞争条件)。所有的问题都是关于如何调用代码和识别文件的机制。
实时!=轮询
您可以通过拆分工作负载来增加容量-但这只是一种临时的解决方法。移动,或者更好的是,删除文件会给你更多的空间,但这仍然是一个丑陋的解决方案。
劳伦斯确实提出了一个好建议。
https://stackoverflow.com/questions/44517916
复制相似问题