Laravel Eloquent分块插入超5万条数据丢失,求百万级Excel同步方案
百万级Excel数据批量插入与每日更新解决方案
问题背景
- 现有一张超100万行的Excel表,已通过Maatwebsite Excel库将数据导入临时表
products_temp,需要将数据完整插入正式表products;后续需每日对比该Excel表,更新正式表中的MSRP和价格列。
当前插入尝试及问题
1. 集合映射+分块插入方案
获取临时表数据的代码:
$temp_products = ProductTemp::limit(100000)->get()->map(function(ProductTemp $temp_product) { return [ 'msrp' => $temp_product->msrp, 'price' => $temp_product->unit_price, 'product_overview' => $temp_product->part_description, 'manufacturer_id' => $temp_product->manufacturer_id, 'upc' => $temp_product->upc, 'manufacturer_part_number' => $temp_product->part_no ]; });
尝试用chunk()和array_chunk()拆分数据:
// $chunks = $temp_products->chunk(5000); $arr_chunks = array_chunk($temp_products->toArray(), 5000);
array_chunk()循环插入代码:
foreach($arr_chunks as $chunk) { Product::insert($chunk); }
chunk()循环插入代码:
foreach($arr_chunks as $chunk) { Product::insert($chunk->toArray()); }
问题表现
- 插入数据量超过5万条后,出现数据丢失或重复的情况;调整块大小(100、1000)后问题依旧,且页面加载无法完成。
- 完整执行函数代码:
public function insertFromTempTable() { // dd("HERE 1111111 22222222222 4444444444"); $temp_products = ProductTemp::all()->map(function (ProductTemp $temp_product) { return [ 'msrp' => $temp_product->msrp, 'price' => $temp_product->unit_price, 'product_overview' => $temp_product->part_description, 'manufacturer_id' => $temp_product->manufacturer_id, 'upc' => $temp_product->upc, 'manufacturer_part_number' => $temp_product->part_no, ]; }); // dd($temp_products); $inc = 0; dump("Started on: " . Carbon::now()->toDateTimeString()); // sleep(10); // foreach ($temp_products as $value) { // Product::insert($temp_products[$inc]); // $inc++; // } // dd($temp_products->toArray()); // Product::insert($temp_products->toArray()); // $chunks = $temp_products->chunk(100); $chunk_sub = 5000; $arr_chunks = array_chunk($temp_products->toArray(), $chunk_sub); // dd($arr_chunks[0]); // dd(gettype($chunks[0]->toArray())); // dd($chunks[0]->toArray()); $chunk_temp = 0; foreach ($arr_chunks as $chunk) { // dd($chunk->toArray()); // dump(count($chunk->toArray())); // Product::insert($chunk->toArray()); $chunk_temp = $chunk_temp + $chunk_sub; Product::insert($chunk); } // $temp_products->chunk(2, function ($subset) { // dd("HHHHHHH"); // $subset->each(function ($item) { // dd($item); // }); // }); dump("Ended on: " . Carbon::now()->toDateTimeString()); }
更新01:原生查询插入的异常
尝试使用insertUsing原生查询批量插入:
$results = DB::table('products')->insertUsing( ['msrp', 'price', 'product_overview', 'manufacturer_id', 'upc', 'manufacturer_part_number',], function ($query) { $query ->select(['msrp', 'unit_price', 'part_description', 'manufacturer_id', 'upc', 'part_no',]) ->from('products_temp'); } );
- 临时表实际有1048575行,
$results返回值为1048575,但正式表仅插入1039229行,存在数据缺失。
核心需求
- 解决百万级数据从临时表到正式表的完整插入问题,避免数据丢失/重复、页面超时等情况。
- 实现每日对比超100万行Excel表,高效更新正式表中MSRP和价格列的最优方案。
内容的提问来源于stack exchange,提问作者Haider Akbar
相关产品推荐
相关产品推荐

