我有一个简单的任务,可以将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'"));
}
对于每个部门,这需要大约一分钟,如果运行它们将在一周内完成或某事......这不是一种选择。
答案 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与代码)查看扇区可能需要的代码更改?