比foreach更快的查询

时间:2016-10-08 09:45:18

标签: php mysql query-optimization

我有一个简单的任务,可以将id从一个表更新到另一个表。 但是我当前的解决方案非常慢,并且运行php和mysql。 Sector表有大约9000条记录,源表有17Mil。 $ sector->代码是varchar

到目前为止,我得到了这个:

foreach(Sector::orderBy('id','DESC')->get() as $sector){
        DB::select(DB::raw("UPDATE `sources` SET `sector_id` = $sector->id WHERE `sector` = '$sector->code'"));
    }

对于每个部门,这需要大约一分钟,如果运行它们将在一周内完成或某事......这不是一种选择。

3 个答案:

答案 0 :(得分:0)

首先,数据库应该有索引。 17Mil条目需要有sector的索引。这意味着对于每个扇区,只会检查与该扇区匹配的记录子集。

其次,这应该可以在单个查询中实现。

UPDATE `sources`,`sector` SET `sources`.`sector_id` = `sector`.`id` 
        WHERE `sources`.`sector` = `sector`.`code`;

这会停止表格的多次转换,并且还应加快更新速度。

参考文献: - MySql : Update syntax - 如何在mySql中进行多表查询。

答案 1 :(得分:0)

我认为这个问题有2个解决方案。

解决方案1 ​​

针对您的问题,最佳和最适合的解决方案是创建一个cron作业,并定期执行(最好是在晚上)。它会解决你的头痛问题。

这是管理cron作业https://code.tutsplus.com/tutorials/managing-cron-jobs-with-php--net-19428的链接。

解决方案2

解决方案2是优化您当前的代码,在编码标准中,有一条规则声明永远不会在循环中编写查询

步骤1:尝试使用单一查询更新数据库

 UPDATE sources
 SET sector_id= (CASE id WHEN 1 THEN 'XXX'
                 WHEN 2 THEN 'XXXX'
                 WHEN 3 THEN 'XXXX'
         END)
WHERE id IN(1,2 ,3);

答案 2 :(得分:0)

UPDATEing 17M行缓慢的原因有很多。其中之一就是如果发生崩溃,InnoDB会将信息构建到ROLLBACK。对于如此大的桌子而言,这尤其昂贵。

我会考虑" chunking"表格一次分为1K或10K行,基于(最好)PRIMARY KEY进行扫描。 Here更多的讨论是这样的。

请记住,在这么大的更新过程中,该表会在某种程度上阻止其他用法。您是否会在更新期间停止所有其他活动(但是已实施)?如果不是,您是否通过部分更新的表的分支,和/或以不同方式(id与代码)查看扇区可能需要的代码更改?