当写脚本循环更新几百万数据发现很慢怎么办 - 孙龙

news/2025/9/22 17:31:53/文章来源:https://www.cnblogs.com/sunlong88/p/19105686

1. 核心逻辑:CASE WHEN条件更新

UPDATE table 
SET order_items_id = CASE WHEN stock_out_item_id = 1 THEN 100WHEN stock_out_item_id = 2 THEN 200ELSE order_items_id END
WHERE stock_out_item_id IN (1,2)
  • 原理:通过单条SQL实现多条记录的条件更新,每个WHEN对应一个stock_out_item_idorder_item_id的映射
  • ELSE保留原值:确保不在更新列表中的记录保持不变
  • WHERE IN过滤:仅更新指定ID的记录,避免全表扫描

以php代码为例

public function handle(){$this->syncStockoutItemsSaleOrderItemsIdV2();}public function syncStockoutItemsSaleOrderItemsIdV2(){// 关闭查询日志以减少内存使用DB::connection('mysql')->disableQueryLog();// 记录开始时间$startTime = microtime(true);$updatedCount = 0;DB::connection("mysql")->table('lie_stock_out_items')->orderBy("stock_out_item_id","desc")->where("order_items_id",0)->where("ext_info","like","%order_item_id%")->chunk(5000, function ($stockOutItemsList) use (&$updatedCount) {// 准备批量更新的数据$itemsUpdateData = []; // 用于lie_stock_out_items表的更新数据$reportUpdateData = []; // 用于lie_stock_out_report表的更新数据foreach($stockOutItemsList as $stockOutItems){$extinfo = json_decode($stockOutItems->ext_info, true);if(!empty($extinfo) && !empty($extinfo["order_item_id"])){$stockOutItemId = $stockOutItems->stock_out_item_id;$orderItemId = $extinfo["order_item_id"];// 收集需要更新的数据,使用关联数组存储$itemsUpdateData[$stockOutItemId] = $orderItemId;$reportUpdateData[$stockOutItemId] = $orderItemId;$updatedCount++;}}// dump($itemsUpdateData);// dump($reportUpdateData);// 执行批量更新$this->batchUpdate('lie_stock_out_items', $itemsUpdateData);$this->batchUpdate('lie_stock_out_report', $reportUpdateData);});// 输出执行统计$endTime = microtime(true);$executionTime = round($endTime - $startTime, 2);echo "批量更新完成!共处理 {$updatedCount} 条记录,耗时 {$executionTime} 秒\n";}// 批量更新方法private function batchUpdate($table, $updateData){if(empty($updateData)) return;// 分批处理大数组,每批最多处理2000条,避免SQL语句过长$chunks = array_chunk($updateData, 2000, true);foreach($chunks as $chunk){$cases = [];$params = [];$ids = [];// 构建CASE语句foreach ($chunk as $stockOutItemId => $orderItemId) {$ids[] = $stockOutItemId;$cases[] = "WHEN stock_out_item_id = ? THEN ?";$params[] = $stockOutItemId;$params[] = $orderItemId;}// 执行批量更新$idsStr = implode(',', $ids);$casesStr = implode(' ', $cases);$query = "UPDATE {$table} SET order_items_id = CASE {$casesStr} ELSE order_items_id END WHERE stock_out_item_id IN ({$idsStr})";// dump($query);// dump($params);DB::connection('mysql')->statement($query, $params);}}

分块处理机制(关键优化)

 
$chunks = array_chunk($updateData, 2000, true); // 每批2000条

 

  • 必要性:MySQL对单条SQL语句长度有限制(max_allowed_packet默认4MB),超大数据量会导致:
    • 语法解析失败
    • 内存溢出
    • 网络传输超时
  • 分块策略:保持原始键值对关系(true参数),确保更新时ID与新值正确对应

3. 参数绑定防注入

 
$params = [1,100,2,200]; // 实际绑定值
DB::statement($query, $params); // 使用PDO预处理

 

  • 安全机制:所有动态值通过?占位符绑定,避免SQL注入
  • 参数顺序:绑定顺序需与CASE中的?出现顺序严格对应

4. 性能对比优势

更新方式SQL次数数据库交互事务开销适用场景
传统循环更新 N次 N次 N次 小数据量
本方案 1次 1次 1次 大数据量批量更新
Eloquent批量更新 1次 1次 1次 简单字段更新

执行流程示例

假设输入:

$updateData = [101 => 2001,102 => 2002,// ... 共3000条
];

处理步骤:

  1. 分成2个块(每块2000条)
  2. 生成SQL片段:
-- 块1
UPDATE table 
SET order_items_id = CASE WHEN stock_out_item_id=101 THEN 2001... # 共2000个WHEN
END 
WHERE stock_out_item_id IN (101,102,...,2000)-- 块2
UPDATE table 
SET order_items_id = CASE WHEN stock_out_item_id=2001 THEN 2003... # 剩余1000个WHEN
END 
WHERE stock_out_item_id IN (2001,2002,...,3000)

这种方案在百万级数据更新场景下,比传统循环更新快10倍以上,同时避免内存溢出风险,是Laravel中处理大数据量更新的标准实践。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年9月Java后端招聘市场技术风向标:666份招聘数据深度解读

2025年9月Java后端招聘市场技术风向标:666份招聘数据深度解读作为一名开发者或技术决策者,你是否想知道当前企业最需要什么技术?为了回答这个问题,我们分析了2025年9月从BOSS直聘平台收集的666份Java后端开发相关的…

服装采购跟单系统的高效管理实践 - 详解

服装采购跟单系统的高效管理实践 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mo…

和汽车相关的国内期刊

永远渴望,大智若愚(stay hungry, stay foolish)

自己建网站写小说可行吗网站界面设计和ios移动界面设计的区别

1.注册建造师应当在相应的岗位上执业。但同时,国家鼓励和提倡注册建造师( )。 A.一师多岗 B.一师全岗 C.一师专岗 D.专岗专职 正确 正确答案:左边查询 学生答案:A 2.下列规范性文件中,效力最高的是( )。 A.地方性法规 B.行政法规 C.行政规章…

小企业网站推广设计国外网站有哪些

esb 和 开源esbJavaOne 2015即将结束,这又是一次很棒的社区活动。 我和Rafael进行了两次会议和一次HOL 。 我最喜欢的会议之一实际上是:谈论ESB,如果今天完成的话。 我以为那是过去? 我通常也倾向于这样说。 但是,系统…

北京网站优化流程适合新手做的小生意

题目描述 移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nu…

营口网站优化网站建设与网页制作盒子模型

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

价格划算的东莞建网站公司桂林什么公司做网站推广好

深入理解 Spring Boot:核心知识与约定大于配置原则 简单说一下为什么要有 Spring Boot? 因为 Spring 的缺点。 虽然 Spring 的组件代码是轻量级的,但它的配置却是重量级的(需要大量 XML 配置) 为了减少配置文件,简化开发 Spri…

苏州哪个公司做门户网站成都建好的网站出租

2019独角兽企业重金招聘Python工程师标准>>> list Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。 比如,列出班里所有同学的名字,就可以用一个list表示: >…

做网站后台的电子文库无锡微信网站定制

javafx 使用像我这样的JavaFX爱好者反复面对的一个问题是何时(或为什么)使用JavaFX代替HTML(5)。 这是我的两分钱: 如果…,则应使用JavaFX。 …您对坚固性/质量感兴趣。 JavaFX是Java! 您将能…

服务器CPU、内存、磁盘、网络使用率,东方通CPU使用率东方通内存使用率监控脚本

#!/bin/bash # 创建日志目录LOG_DIR="/log"LOG_FILE="$LOG_DIR/jk.txt" # 阈值设置CPU_THRESHOLD=80 # CPU使用率阈值(%)MEM_THRESHOLD=80 # 内存使用率阈值(%)DISK_THRESHOL…

3 网络基础知识+web基础知识+部署Server

3.1网络基础 3.1.1 OSI七层模型 # 一种理论上的网络通信模型,实践中未应用;从底层到上层分别是物理层、数据链路层、网络层、传输层、会话层、表示层、应用层 * 物理层:物理介质传输比特流,如电缆、光缆 * 数据链路…

什么是 AutoModel

什么是 AutoModelAutoModel 加载模型”是指使用 Hugging Face Transformers 库提供的 AutoModel 系列类,根据模型名称自动识别并加载对应的预训练模型结构和权重,从而无需手动指定具体模型类(如 BertModel、GPT2Mod…

深入解析:STM32——WDG看门狗

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

wxpython图形界面_01_最小基本结构

import wx# 创建应用程序对象 app = wx.App()# 创建窗口对象 frm = wx.Frame(None, title=第一个应用程序, size=(800, 600), pos=(200, 50))# 显示窗口 frm.Show()# 进入主事件循环 app.MainLoop()

做网站最小的字体是多少网站租用 凡

介绍Objects Comparer是用于对象比较的工具,c#常见的数据结构都是可以用这个三方库进行对比,比较复杂的对象也是可以比较的。简而言之,Objects Comparer 是一个对象到对象的比较器,它允许逐个成员递归得比较对象,并为某…

漳州建设银行网站首页珠海知业科技

能实现不出家门就可以通过网络进行系统管理,交易等,而且过程简单、快捷。同样的,在人们的工作生活中,也就需要互联网技术来方便人们的日常工作生活,实现工作办公的自动化处理,实现信息化,无纸化…

万网网站域名wordpress 黄蓝 现代企业

【ADB全称 Android Debug Bridge】 是Android SDK中的一个命令行工具adb命令可以直接操作管理Android模拟器或真实的Android设备(手机) 建立PC和模拟器连接 # 建立连接 adb connect 127.0.1: 模拟器端口号〈逍遥模拟器21503〉 # 验证是否连接成功 adb d…

朝阳周边网站建设办公管理软件定制

在当今信息爆炸的时代,人工智能在各行各业都发挥着越来越重要的作用,高校教育领域也不例外。最近,越来越多的高校开始陆续拥抱chatgpt(Chatbot GPT)这一人工智能技术,在学术领域会带来了怎样的变化与影响&a…

湖南网站设计外包费用制作网页可用邮件合并吗

前情:上一篇实际是让AI工具帮我总结了一下讨论的内容,这里把讨论的过程贴出来,这个讨论是为解决实际问题 前文https://blog.csdn.net/wgdzg/article/details/145039446 问题说明: 我使用 docker compose 管理我的容器&#xff0…