【问题标题】:Laravel-Excel 2, Insert data fasterLaravel-Excel 2,更快地插入数据
【发布时间】:2018-10-23 14:29:31
【问题描述】:

这是我用来将 excel(使用 Maatwebsite Laravel-Excel 2)文件导入我的数据库的方法的主要代码:

$data = Excel::selectSheetsByIndex(0)->load($file, function($reader) {})->get()->toArray();
DB::beginTransaction();
try {
    foreach ($data as $key => $value) {
        $med= trim($value["med"]);
        $serial = trim($value["nro.seriemedidor"]);

        DB::table('medidores')->insert([
            "med" => $med,
            "serial_number" => $serial
        ]);
    }
    DB::commit();
} catch (\Exception $e) {
    DB::rollback();
    return redirect()->route('myroute')->withErrors("Some error message");
}

当我的数据“很少”时(假设 excel 文件中的行数少于 5000 行),这可以正常工作。但我需要处理一个大的 excel 文件,它有 140 万行,分成超过 1 张。我怎样才能使我的方法更快?有什么建议吗?

编辑:我将使用答案的其中一个 cmets 的链接上的代码编辑问题:

$data = Excel::selectSheetsByIndex(0)->load($file, function($reader) {})->get()->toArray();
DB::beginTransaction();
try {
  $bulk_data = [];
  foreach ($data as $key => $value) {
    $med= trim($value["med"]);
    $serial = trim($value["nro.seriemedidor"]);
    $bulk_data[] = ["med" => $med,"serial_number" => $serial] ;
  }
  $collection = collect($bulk_data);   //turn data into collection
  $chunks = $collection->chunk(100); //split into chunk of 100's
  $chunks->toArray(); //convert chunk to array
 //loop through chunks:
 foreach($chunks as $chunk)
 {
   DB::table('medidores')->insert($chunk->toArray());
 }
  DB::commit();
} catch (\Exception $e) {
  DB::rollback();
  return redirect()->route('myroute')->withErrors("Some error message");
}

大块的东西对我有用。

【问题讨论】:

    标签: laravel laravel-query-builder laravel-excel


    【解决方案1】:

    是的,你可以,而不是执行 X(数据库请求数)* N(工作表数)尝试做一个简单的批量插入,这只会让你花费循环遍历数据保存 X * N 数据库请求的复杂性,这里有一个示例:

    $data = Excel::selectSheetsByIndex(0)->load($file, function($reader) {})->get()->toArray();
    DB::beginTransaction();
    try {
      $bulk_data = [];
      foreach ($data as $key => $value) {
         $med= trim($value["med"]);
         $serial = trim($value["nro.seriemedidor"]);
         $bulk_data[] = ["med" => $med,"serial_number" => $serial] ;
      }
      DB::table('medidores')->insert($bulk_data);
      DB::commit();
    } catch (\Exception $e) {
      DB::rollback();
      return redirect()->route('myroute')->withErrors("Some error message");
    }
    

    您可以参考此答案以获取有关 db requests 的更多说明: https://stackoverflow.com/a/1793209/8008456

    【讨论】:

    • 嗯我知道这是有道理的,但我正在我的代码中做一个基准测试,我的代码需要 9 秒才能插入 5000 行。阵列最终花了 14 秒...如果您不相信我,我可以制作它的视频。
    • 实际上我已经在 MariaDB 和 PostgreSQL 中测试了两个不同的项目,分别是 Laravel 5.4 和 5.6。在 foreach 中插入总是更快,我不知道为什么。
    • 不错!我用我拥有的另一个插件进行了测试,它花了 30 秒而不是 45. 50% 快。我会尝试另一个。
    • 似乎您必须在插入时(不循环主数据)在数据库请求和内部循环之间分配复杂性,尝试增加/减少块大小并查看会发生什么。
    • 有空时尝试使用这个包github.com/rap2hpoutre/fast-excel#benchmarks 它是 Spout 包的一个包装器,相信可以为您提供更好的结果,我还没有尝试过,但基准测试似乎很有趣。编辑:(有人提到不要相信他们的基准LOL)
    猜你喜欢
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多