一、业务场景实际开发中经常遇到跨表数据迁移、数据备份、错题数据归集等场景根据一批指定ID从源表批量查询符合条件的数据同步写入目标数据表并且统一追加一批公共固定字段数据实现批量数据复刻入库。二、传统写法存在的性能痛点常规开发思路为循环查询单条数据、组装数据、逐条新增入库。这种方式在少量数据下差异不大但当ID数量多、数据量级变大后会出现严重的性能损耗。该方案会产生多次代码与数据库的IO交互查询、组装、入库分步执行交互次数随数据量线性递增。频繁的数据库请求、网络传输、程序循环运算极大占用服务器资源执行效率极低数据量越大性能短板越明显。三、高性能解决方案放弃各类编程语言通用的循环逐条读写模式采用 MySQL 原生INSERT INTO ... SELECT批量语法不依赖各语言循环组装、分批入库逻辑一次性完成「数据查询、字段拼接、批量入库」全流程适配 PHP、Java、Go、C#、ASP、Rust 等所有开发语言。通过IN条件筛选指定数据源查询源表数据的同时直接拼接统一固定公共字段整体一次性写入目标表极简高效。-- 【通用核心SQL】全语言适配Java/Go/C#/ASP/Rust/PHP 均可直接调用执行 -- 适配所有后端语言仅需根据语言规则拼接参数、执行SQL即可-- 【通用核心SQL】全语言适配Java/Go/C#/ASP/Rust/PHP 均可直接调用执行 -- 适配所有后端语言仅需根据语言规则拼接参数、执行SQL即可 INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段, ? AS create_ip, ? AS create_time, ? AS data_y, ? AS data_m, ? AS data_d, ? AS test_id, ? AS simulator_record_id FROM 源表 WHERE 关联ID IN (?) -- 优势所有语言无需写循环、数据组装逻辑仅传参执行SQL即可-- 优势所有语言无需写循环、数据组装逻辑仅传参执行SQL即可四、方案核心优势1. 极致减少IO交互性能大幅提升传统写法是N次查询N次入库双重循环消耗资源本方案仅执行单次数据库交互所有数据筛选、字段拼接、入库操作均在数据库层完成彻底规避PHP与数据库频繁通讯的性能开销。2. 数据库层原生执行效率更高INSERT SELECT 是MySQL原生优化语法底层执行效率远高于PHP循环组装数据。数据量越大新旧方案的性能差距越悬殊海量数据批量迁移优势极其明显。3. 代码简洁、维护性强无需各语言编写复杂循环、数据组装、分片批量等冗余逻辑核心能力完全依托MySQL原生语法实现代码极简、通用性极强同时规避了多语言循环超时、内存溢出、分片异常等常见问题项目维护性与稳定性大幅提升。五、多语言实战代码示例参数化安全写法以下所有示例均基于上方通用SQL采用参数化预编译杜绝SQL注入可直接适配项目业务无需改造核心逻辑。1. PHP 实现// 固定公共参数 $params [ 127.0.0.1, date(Y-m-d H:i:s), date(Y), date(m), date(d), 100, 2001 ]; // 待筛选ID数组 $ids [1,2,3,4,5]; $inStr implode(,, $ids); // 执行原生SQL $sql INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,?,?,?,?,?,?,? FROM 源表 WHERE 关联ID IN ({$inStr}); Db::execute($sql, $params);2. Java 实现MyBatis// 封装参数 MapString, Object paramMap new HashMap(); paramMap.put(createIp, 127.0.0.1); paramMap.put(createTime, new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date())); paramMap.put(dataY, new SimpleDateFormat(yyyy).format(new Date())); paramMap.put(dataM, new SimpleDateFormat(MM).format(new Date())); paramMap.put(dataD, new SimpleDateFormat(dd).format(new Date())); paramMap.put(testId, 100); paramMap.put(simulatorRecordId, 2001); paramMap.put(idList, Arrays.asList(1,2,3,4,5)); // Mapper层直接执行 int batchInsert(Mapper paramMap);insert idbatchInsert INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,#{createIp},#{createTime},#{dataY},#{dataM},#{dataD},#{testId},#{simulatorRecordId} FROM 源表 WHERE 关联ID IN foreach collectionidList open( close) separator, itemid#{id}/foreach /insert3. Go 实现GORMimport gorm.io/gorm // 定义参数 createIp : 127.0.0.1 createTime : time.Now().Format(2006-01-02 15:04:05) dataY : time.Now().Format(2006) dataM : time.Now().Format(01) dataD : time.Now().Format(02) testId : 100 simulatorRecordId : 2001 idList : []int{1,2,3,4,5} // 批量执行迁移插入 db.Exec(INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,?,?,?,?,?,?,? FROM 源表 WHERE 关联ID IN (?), createIp, createTime, dataY, dataM, dataD, testId, simulatorRecordId, idList)4. C# 实现ADO.NET// 基础参数赋值 string createIp 127.0.0.1; string createTime DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss); string dataY DateTime.Now.ToString(yyyy); string dataM DateTime.Now.ToString(MM); string dataD DateTime.Now.ToString(dd); int testId 100; int simulatorRecordId 2001; Listint ids new Listint { 1,2,3,4,5 }; string inSql string.Join(,, ids); string sql INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,ip,time,y,m,d,test,sim FROM 源表 WHERE 关联ID IN ( inSql ); // 参数化执行 SqlCommand cmd new SqlCommand(sql, conn); cmd.Parameters.AddWithValue(ip, createIp); cmd.Parameters.AddWithValue(time, createTime); cmd.Parameters.AddWithValue(y, dataY); cmd.Parameters.AddWithValue(m, dataM); cmd.Parameters.AddWithValue(d, dataD); cmd.Parameters.AddWithValue(test, testId); cmd.Parameters.AddWithValue(sim, simulatorRecordId); cmd.ExecuteNonQuery();5. ASP 经典实现% 基础参数 Dim createIp,createTime,dataY,dataM,dataD,testId,simulatorRecordId,inStr createIp 127.0.0.1 createTime Year(Now)-Month(Now)-Day(Now) Hour(Now):Minute(Now):Second(Now) dataY Year(Now) dataM Month(Now) dataD Day(Now) testId 100 simulatorRecordId 2001 inStr 1,2,3,4,5 执行SQL Dim sql sql INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) _ SELECT 源表.基础业务字段,createIp,createTime,dataY,dataM,dataD,testId,simulatorRecordId FROM 源表 WHERE 关联ID IN (inStr) Conn.Execute(sql) %6. Rust 实现sqlxuse sqlx::mysql::MySqlPool; use chrono::Local; // 异步批量插入 async fn batch_migrate(pool: MySqlPool) - Result(), sqlx::Error { let create_ip 127.0.0.1; let now Local::now(); let create_time now.format(%Y-%m-%d %H:%M:%S).to_string(); let data_y now.format(%Y).to_string(); let data_m now.format(%m).to_string(); let data_d now.format(%d).to_string(); let test_id 100; let simulator_record_id 2001; let id_list vec![1,2,3,4,5]; let in_str: VecString id_list.iter().map(|x| x.to_string()).collect(); let in_str in_str.join(,); // 执行SQL sqlx::query(format!(r# INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,?,?,?,?,?,?,? FROM 源表 WHERE 关联ID IN ({}) #, in_str)) .bind(create_ip) .bind(create_time) .bind(data_y) .bind(data_m) .bind(data_d) .bind(test_id) .bind(simulator_record_id) .execute(pool) .await?; Ok(()) }人人皆为创造者共创方能共成长每个人都是使用者也是创造者是数字世界的消费者更是价值的生产者与分享者。在智能时代的浪潮里单打独斗的发展模式早已落幕唯有开放连接、创意共创、利益共享才能让个体价值汇聚成生态合力让技术与创意双向奔赴实现平台与伙伴的快速成长、共赢致远。原创永久分成共赴星辰大海原创创意共创、永久收益分成是东方仙盟始终坚守的核心理念。我们坚信每一份原创智慧都值得被尊重与回馈以永久分成锚定共创初心让创意者长期享有价值红利携手万千伙伴向着科技星辰大海笃定前行拥抱硅基 生命与数字智能交融的未来共筑跨越时代的数字文明共同体。东方仙盟拥抱知识开源共筑数字新生态在全球化与数字化浪潮中东方仙盟始终秉持开放协作、知识共享的理念积极拥抱开源技术与开放标准。我们相信唯有打破技术壁垒、汇聚全球智慧才能真正推动行业的可持续发展。开源赋能中小商户通过将前端异常检测、跨系统数据互联等核心能力开源化东方仙盟为全球中小商户提供了低成本、高可靠的技术解决方案让更多商家能够平等享受数字转型的红利。共建行业标准我们积极参与国际技术社区与全球开发者、合作伙伴共同制定开放协议 与技术规范推动跨境零售、文旅、餐饮等多业态的系统互联互通构建更加公平、高效的数字生态。知识普惠共促发展通过开源社区 、技术文档与培训体系东方仙盟致力于将前沿技术转化为可落地的行业实践赋能全球合作伙伴共同培育创新人才推动数字经济 的普惠式增长阿雪技术观在科技发展浪潮中我们不妨积极投身技术共享。不满足于做受益者更要主动担当贡献者 。无论是分享代码、撰写技术博客还是参与开源项目 维护改进每一个微小举动都可能蕴含推动技术进步的巨大能量。东方仙盟是汇聚力量的天地我们携手在此探索硅基 生命为科技进步添砖加瓦。Hey folks, in this wild tech - driven world, why not dive headfirst into the whole tech - sharing scene? Dont just be the one reaping all the benefits; step up and be a contributor too. Whether youre tossing out your code snippets , hammering out some tech blogs, or getting your hands dirty with maintaining and sprucing up open - source projects, every little thing you do might just end up being a massive force that pushes tech forward. And guess what? The Eastern FairyAlliance is this awesome place where we all come together. Were gonna team up and explore the whole silicon - based life thing, and in the process, well be fueling the growth of technology
数据库优化(十)MySQL批量复制插入数 ——东方仙盟
一、业务场景实际开发中经常遇到跨表数据迁移、数据备份、错题数据归集等场景根据一批指定ID从源表批量查询符合条件的数据同步写入目标数据表并且统一追加一批公共固定字段数据实现批量数据复刻入库。二、传统写法存在的性能痛点常规开发思路为循环查询单条数据、组装数据、逐条新增入库。这种方式在少量数据下差异不大但当ID数量多、数据量级变大后会出现严重的性能损耗。该方案会产生多次代码与数据库的IO交互查询、组装、入库分步执行交互次数随数据量线性递增。频繁的数据库请求、网络传输、程序循环运算极大占用服务器资源执行效率极低数据量越大性能短板越明显。三、高性能解决方案放弃各类编程语言通用的循环逐条读写模式采用 MySQL 原生INSERT INTO ... SELECT批量语法不依赖各语言循环组装、分批入库逻辑一次性完成「数据查询、字段拼接、批量入库」全流程适配 PHP、Java、Go、C#、ASP、Rust 等所有开发语言。通过IN条件筛选指定数据源查询源表数据的同时直接拼接统一固定公共字段整体一次性写入目标表极简高效。-- 【通用核心SQL】全语言适配Java/Go/C#/ASP/Rust/PHP 均可直接调用执行 -- 适配所有后端语言仅需根据语言规则拼接参数、执行SQL即可-- 【通用核心SQL】全语言适配Java/Go/C#/ASP/Rust/PHP 均可直接调用执行 -- 适配所有后端语言仅需根据语言规则拼接参数、执行SQL即可 INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段, ? AS create_ip, ? AS create_time, ? AS data_y, ? AS data_m, ? AS data_d, ? AS test_id, ? AS simulator_record_id FROM 源表 WHERE 关联ID IN (?) -- 优势所有语言无需写循环、数据组装逻辑仅传参执行SQL即可-- 优势所有语言无需写循环、数据组装逻辑仅传参执行SQL即可四、方案核心优势1. 极致减少IO交互性能大幅提升传统写法是N次查询N次入库双重循环消耗资源本方案仅执行单次数据库交互所有数据筛选、字段拼接、入库操作均在数据库层完成彻底规避PHP与数据库频繁通讯的性能开销。2. 数据库层原生执行效率更高INSERT SELECT 是MySQL原生优化语法底层执行效率远高于PHP循环组装数据。数据量越大新旧方案的性能差距越悬殊海量数据批量迁移优势极其明显。3. 代码简洁、维护性强无需各语言编写复杂循环、数据组装、分片批量等冗余逻辑核心能力完全依托MySQL原生语法实现代码极简、通用性极强同时规避了多语言循环超时、内存溢出、分片异常等常见问题项目维护性与稳定性大幅提升。五、多语言实战代码示例参数化安全写法以下所有示例均基于上方通用SQL采用参数化预编译杜绝SQL注入可直接适配项目业务无需改造核心逻辑。1. PHP 实现// 固定公共参数 $params [ 127.0.0.1, date(Y-m-d H:i:s), date(Y), date(m), date(d), 100, 2001 ]; // 待筛选ID数组 $ids [1,2,3,4,5]; $inStr implode(,, $ids); // 执行原生SQL $sql INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,?,?,?,?,?,?,? FROM 源表 WHERE 关联ID IN ({$inStr}); Db::execute($sql, $params);2. Java 实现MyBatis// 封装参数 MapString, Object paramMap new HashMap(); paramMap.put(createIp, 127.0.0.1); paramMap.put(createTime, new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date())); paramMap.put(dataY, new SimpleDateFormat(yyyy).format(new Date())); paramMap.put(dataM, new SimpleDateFormat(MM).format(new Date())); paramMap.put(dataD, new SimpleDateFormat(dd).format(new Date())); paramMap.put(testId, 100); paramMap.put(simulatorRecordId, 2001); paramMap.put(idList, Arrays.asList(1,2,3,4,5)); // Mapper层直接执行 int batchInsert(Mapper paramMap);insert idbatchInsert INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,#{createIp},#{createTime},#{dataY},#{dataM},#{dataD},#{testId},#{simulatorRecordId} FROM 源表 WHERE 关联ID IN foreach collectionidList open( close) separator, itemid#{id}/foreach /insert3. Go 实现GORMimport gorm.io/gorm // 定义参数 createIp : 127.0.0.1 createTime : time.Now().Format(2006-01-02 15:04:05) dataY : time.Now().Format(2006) dataM : time.Now().Format(01) dataD : time.Now().Format(02) testId : 100 simulatorRecordId : 2001 idList : []int{1,2,3,4,5} // 批量执行迁移插入 db.Exec(INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,?,?,?,?,?,?,? FROM 源表 WHERE 关联ID IN (?), createIp, createTime, dataY, dataM, dataD, testId, simulatorRecordId, idList)4. C# 实现ADO.NET// 基础参数赋值 string createIp 127.0.0.1; string createTime DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss); string dataY DateTime.Now.ToString(yyyy); string dataM DateTime.Now.ToString(MM); string dataD DateTime.Now.ToString(dd); int testId 100; int simulatorRecordId 2001; Listint ids new Listint { 1,2,3,4,5 }; string inSql string.Join(,, ids); string sql INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,ip,time,y,m,d,test,sim FROM 源表 WHERE 关联ID IN ( inSql ); // 参数化执行 SqlCommand cmd new SqlCommand(sql, conn); cmd.Parameters.AddWithValue(ip, createIp); cmd.Parameters.AddWithValue(time, createTime); cmd.Parameters.AddWithValue(y, dataY); cmd.Parameters.AddWithValue(m, dataM); cmd.Parameters.AddWithValue(d, dataD); cmd.Parameters.AddWithValue(test, testId); cmd.Parameters.AddWithValue(sim, simulatorRecordId); cmd.ExecuteNonQuery();5. ASP 经典实现% 基础参数 Dim createIp,createTime,dataY,dataM,dataD,testId,simulatorRecordId,inStr createIp 127.0.0.1 createTime Year(Now)-Month(Now)-Day(Now) Hour(Now):Minute(Now):Second(Now) dataY Year(Now) dataM Month(Now) dataD Day(Now) testId 100 simulatorRecordId 2001 inStr 1,2,3,4,5 执行SQL Dim sql sql INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) _ SELECT 源表.基础业务字段,createIp,createTime,dataY,dataM,dataD,testId,simulatorRecordId FROM 源表 WHERE 关联ID IN (inStr) Conn.Execute(sql) %6. Rust 实现sqlxuse sqlx::mysql::MySqlPool; use chrono::Local; // 异步批量插入 async fn batch_migrate(pool: MySqlPool) - Result(), sqlx::Error { let create_ip 127.0.0.1; let now Local::now(); let create_time now.format(%Y-%m-%d %H:%M:%S).to_string(); let data_y now.format(%Y).to_string(); let data_m now.format(%m).to_string(); let data_d now.format(%d).to_string(); let test_id 100; let simulator_record_id 2001; let id_list vec![1,2,3,4,5]; let in_str: VecString id_list.iter().map(|x| x.to_string()).collect(); let in_str in_str.join(,); // 执行SQL sqlx::query(format!(r# INSERT INTO 目标表(基础业务字段,create_ip,create_time,data_y,data_m,data_d,test_id,simulator_record_id) SELECT 源表.基础业务字段,?,?,?,?,?,?,? FROM 源表 WHERE 关联ID IN ({}) #, in_str)) .bind(create_ip) .bind(create_time) .bind(data_y) .bind(data_m) .bind(data_d) .bind(test_id) .bind(simulator_record_id) .execute(pool) .await?; Ok(()) }人人皆为创造者共创方能共成长每个人都是使用者也是创造者是数字世界的消费者更是价值的生产者与分享者。在智能时代的浪潮里单打独斗的发展模式早已落幕唯有开放连接、创意共创、利益共享才能让个体价值汇聚成生态合力让技术与创意双向奔赴实现平台与伙伴的快速成长、共赢致远。原创永久分成共赴星辰大海原创创意共创、永久收益分成是东方仙盟始终坚守的核心理念。我们坚信每一份原创智慧都值得被尊重与回馈以永久分成锚定共创初心让创意者长期享有价值红利携手万千伙伴向着科技星辰大海笃定前行拥抱硅基 生命与数字智能交融的未来共筑跨越时代的数字文明共同体。东方仙盟拥抱知识开源共筑数字新生态在全球化与数字化浪潮中东方仙盟始终秉持开放协作、知识共享的理念积极拥抱开源技术与开放标准。我们相信唯有打破技术壁垒、汇聚全球智慧才能真正推动行业的可持续发展。开源赋能中小商户通过将前端异常检测、跨系统数据互联等核心能力开源化东方仙盟为全球中小商户提供了低成本、高可靠的技术解决方案让更多商家能够平等享受数字转型的红利。共建行业标准我们积极参与国际技术社区与全球开发者、合作伙伴共同制定开放协议 与技术规范推动跨境零售、文旅、餐饮等多业态的系统互联互通构建更加公平、高效的数字生态。知识普惠共促发展通过开源社区 、技术文档与培训体系东方仙盟致力于将前沿技术转化为可落地的行业实践赋能全球合作伙伴共同培育创新人才推动数字经济 的普惠式增长阿雪技术观在科技发展浪潮中我们不妨积极投身技术共享。不满足于做受益者更要主动担当贡献者 。无论是分享代码、撰写技术博客还是参与开源项目 维护改进每一个微小举动都可能蕴含推动技术进步的巨大能量。东方仙盟是汇聚力量的天地我们携手在此探索硅基 生命为科技进步添砖加瓦。Hey folks, in this wild tech - driven world, why not dive headfirst into the whole tech - sharing scene? Dont just be the one reaping all the benefits; step up and be a contributor too. Whether youre tossing out your code snippets , hammering out some tech blogs, or getting your hands dirty with maintaining and sprucing up open - source projects, every little thing you do might just end up being a massive force that pushes tech forward. And guess what? The Eastern FairyAlliance is this awesome place where we all come together. Were gonna team up and explore the whole silicon - based life thing, and in the process, well be fueling the growth of technology