首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP脚本优化,通过FTP摄像头实时更新数据库mysql的文件名数据

PHP脚本优化,通过FTP摄像头实时更新数据库mysql的文件名数据
EN

Stack Overflow用户
提问于 2017-06-13 17:46:46
回答 2查看 54关注 0票数 0

我有一个PHP脚本来更新数据库中的数据,从文件名中获取详细信息

代码语言:javascript
复制
<?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个文件。

如何优化或实现这一点?

到底能做到吗?

EN

回答 2

Stack Overflow用户

发布于 2017-06-13 18:17:13

正如@LawrenceCherone所引用的,您应该检查foreach循环中的每一行,并删除在每次迭代中没有更改的所有内容。例如,new PDO将相对昂贵,并且不需要在每个周期中不断创建新的对象。我想单单这一点就会给你带来很大的进步。

您有两个方面的问题;数据库对象在以下位置创建:

代码语言:javascript
复制
$con=new PDO("mysql:host=localhost;dbname=lpm;","root","password");

并检查该行是否已存在于:

代码语言:javascript
复制
$stmt=$con->prepare('select *from license where(fileName=:fileName)');

顺便说一句,我不熟悉你的方括号语法,它看起来效率很低,而且你在* from之间缺少空格是一个语法错误。

因此,第一部分:只创建一次内容

修复数据库对象创建,使其在页面加载时仅创建一个对象,而不是每次迭代创建一个对象。

代码语言:javascript
复制
$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)以执行类似以下操作:

代码语言:javascript
复制
 $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上有很多关于这方面的文献。这本书非常值得一读和探索。

示例:

代码语言:javascript
复制
$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
    ));
}
票数 2
EN

Stack Overflow用户

发布于 2017-06-13 18:14:05

“优化”这段代码不会对代码的性能、可伸缩性或功能产生重大影响(至少有一个竞争条件)。所有的问题都是关于如何调用代码和识别文件的机制。

实时!=轮询

您可以通过拆分工作负载来增加容量-但这只是一种临时的解决方法。移动,或者更好的是,删除文件会给你更多的空间,但这仍然是一个丑陋的解决方案。

劳伦斯确实提出了一个好建议。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44517916

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档