如何向数据库插入百万条记录避免系统卡顿与页面无响应
如何向数据库插入百万条记录,避免系统卡顿与页面无响应
核心优化思路
解决这类问题的关键是拆分大任务、降低单次操作的资源占用,同时避免同步阻塞用户请求,具体方案如下:
分块批量插入
一次性插入百万条记录会瞬间占用大量数据库连接和服务器内存,将数据拆分成小批次(比如每10000条一批)插入,能显著降低系统负载,避免卡顿。异步化处理(可选但推荐)
如果是Web页面触发的插入操作,建议把插入逻辑放到异步任务(如Laravel Queue)中执行,前端直接返回成功提示,后台异步完成数据插入,彻底避免页面无响应。
PHP(Laravel)实现示例
$rangeNumber = collect(range($validatedDate['from'], $validatedDate['to'])); $collectData = []; foreach ($rangeNumber as $number){ $collectData[] = [ 'receive_uuid' => $receiveUUID, 'region_id' => $regionId, 'office_id' => $officeId, 'number' => $prefix.str_pad($number, 7, '0', STR_PAD_LEFT), 'description' => '', 'created_at' => Carbon::now(), ]; } // 按10000条数据分块 $dataCollection = collect($collectData)->chunk(10000); // 关闭查询日志,避免内存溢出 DB::disableQueryLog(); foreach ($dataCollection as $data){ DB::table('blanks')->insert($data->toArray()); } session()->flash('MsgSuccess', 'Success'); return $this->redirect(route('blanks'), true);
额外优化建议
- 事务包裹保证数据完整性:如果需要确保所有数据要么全部插入成功,要么全部回滚,可以用事务包裹分块逻辑:
DB::beginTransaction(); try { foreach ($dataCollection as $data){ DB::table('blanks')->insert($data->toArray()); } DB::commit(); } catch (\Exception $e) { DB::rollBack(); // 此处添加错误处理逻辑 } - 队列异步执行:将插入逻辑封装成队列任务,前端无需等待插入完成:
// 分发队列任务,后台异步执行插入 InsertBlanksJob::dispatch($validatedDate, $receiveUUID, $regionId, $officeId, $prefix); - 数据库层面优化:临时关闭
unique_checks和foreign_key_checks(插入完成后恢复)、调整innodb_buffer_pool_size参数,能进一步提升插入速度。
内容的提问来源于stack exchange,提问作者J0KER
相关产品推荐
相关产品推荐

