Laravel插入数据库前快速比对两个关联CSV文件的高效方法
Laravel 双CSV关联导入优化方案
以下方案按照数据量从小到大排序,可根据实际场景选择:
方案1:哈希查找法(适合万级以下数据量,实现成本最低)
核心思路是提前把所有银行账户的user_number提取为以user_number为键的集合,查找时间复杂度直接降到O(1),完全避免嵌套循环。
- 第一步先读取bank_account.csv生成索引集合
// 基于Laravel集合实现,也可替换为原生数组 $bankAccountIndex = collect(file(storage_path('bank_account.csv'))) ->skip(1) // 跳过CSV表头,无表头可删除该行 ->map(function ($row) { $columns = str_getcsv($row); return $columns[0]; // 假设user_number是CSV第一列,按需修改列索引 }) ->flip() // 键值互换,把user_number转为数组键 ->toArray();
- 第二步遍历用户CSV,直接过滤出有对应银行账户的用户
$validUsers = collect(file(storage_path('user.csv'))) ->skip(1) ->map(function ($row) { $columns = str_getcsv($row); return [ 'user_number' => $columns[0], 'name' => $columns[1], // 补充其他用户字段映射 ]; }) ->filter(fn ($user) => isset($bankAccountIndex[$user['user_number']])) ->toArray();
- 第三步批量插入数据库,避免单条插入的IO开销
User::insert($validUsers);
该方案比原始嵌套循环性能提升至少100倍,10万条以内数据基本可以秒处理。
方案2:临时表关联法(适合10万级以上大数据量,性能最优)
如果CSV数据量过大,内存无法装载所有银行账户号,可直接在数据库层完成关联过滤,性能最高。
- 第一步创建临时表存储CSV原始数据,给
user_number加索引
Schema::create('temp_users', function (Blueprint $table) { $table->string('user_number')->index(); $table->string('name'); // 补充其他用户对应字段 }); Schema::create('temp_bank_accounts', function (Blueprint $table) { $table->string('user_number')->index(); // 仅需过滤的话可以只存user_number字段 });
- 第二步用数据库原生导入命令导入CSV,比PHP逐行读取快数倍
// MySQL导入示例,其他数据库对应修改语法即可 DB::statement("LOAD DATA INFILE '" . storage_path('user.csv') . "' INTO TABLE temp_users FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' IGNORE 1 ROWS"); DB::statement("LOAD DATA INFILE '" . storage_path('bank_account.csv') . "' INTO TABLE temp_bank_accounts FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n' IGNORE 1 ROWS");
- 第三步用SQL关联查询直接插入符合要求的用户数据到正式表
DB::statement("INSERT INTO users (user_number, name, 其他字段) SELECT tu.user_number, tu.name, 其他对应字段 FROM temp_users tu INNER JOIN temp_bank_accounts tba ON tu.user_number = tba.user_number");
- 最后删除临时表即可,百万级数据处理耗时通常在10秒以内。
额外优化提示
- 导入前可关闭数据库事务自动提交,批量提交减少IO开销
- 如果需要同时导入用户和对应银行账户数据,可在关联查询时同时写入两个正式表
- 注意处理CSV编码、特殊字符转义问题,避免数据解析错误
内容的提问来源于stack exchange,提问作者wandy_candra
相关产品推荐
相关产品推荐

