Laravel 5批量插入与关系

时间:2016-12-17 22:05:49

标签: php mysql performance laravel laravel-5

我需要将大量数据批量插入mysql。大约50万行,与Laravel 5.3中的关系(硬部分)

表格是车辆,用户和user_vehicle

普通车辆插入阵列看起来像这样:

$vehicles = array_chunk($vehicles, 10000);

foreach ($vehicles as $key => $vehicle) {
    Vehicle::insert($vehicle);
}

我可以成功插入这样的记录:

$vehicles = array();
$vehUsers = array();

$users = Users::get();

foreach ($data as $val) {
    // Remap data to right structure
    $temp = array(
        'license_plate' => $val->license_plate,
        'created_at' => $now,
        'updated_at' => $now,
        'state_id' => $activeState,
        'type_id' => $typeId,
    );

    // Search for right user (This part is really slow)
    $userId = $users->where('email', $val->email)->first();
    if ($userId) {
        $userId = $userId->id;
    }

    array_push($vehicles, $temp);

    // Thought that it might help to save them into array for later use
    array_push($vehUsers, $userId);
}

插入所有数据并且一切正常都需要几秒钟,但现在我需要为它们添加关系。 由于一辆车可以属于许多用户(车主,司机等),因此我需要将某些用户附加到某辆车上。

现在,当我尝试在这里添加关系时,我被困住了:

$vehicles = array_chunk($vehicles, 10000);

foreach ($vehicles as $key => $vehicle) {
    Vehicle::insert($vehicle);
    // Need to attach user here somehow
}

但问题是,我不能像这样插入它们

// Insert them and relations one by one and it will take years
foreach ($vehicles as $key => $vehicle) {
    $veh = Vehicle::insert($vehicle);
    $veh->users()->attach($vehUsers[$key]);
}

我需要以批量运行它们(在我的情况下是10k)因为1比1插入需要太长时间

{{1}}

如何批量插入车辆及其关系?

编辑:慢速部分正在进行数据库查询。我可以等待10-20秒让php完成循环项目。

2 个答案:

答案 0 :(得分:1)

首先,加载所有用户。但只选择idemail

$users = User::pluck('email', 'id')->toArray();

这将创建一个[id => email]结构的数组。

然后,您将能够使用此数组而无需执行其他查询:

$userId = $users[$email];

然后将id类型的bigint列添加到vehicle_user数据透视表。为此表创建单独的块数组,并使用批量插入关系而不是使用attach()方法。

答案 1 :(得分:0)

首先,请理解您所遵循的技术是让您一次又一次地遍历$data(实际上非​​常大)。为什么?因为...

  1. 首先用于制作临时变量的循环。
  2. 然后第二个用于插入分块数据的循环。
  3. 第三个for循环查找用户输入相同的电子邮件,然后选择同一用户的Vehicle,然后将其与$user->vehicles()->sync([...Vehicle Ids...]);
  4. 同步

    通过只为一个循环制作一个循环,您可以通过

    简单地完成任务
    foreach($data as $key => $vehicle) {
      $vehicle = Vehicle::create([
                          'license_plate' => $vehicle->license_plate,
                          'state_id' => $activeState,
                          'type_id' => $typeId,
                        ]);
    
      $user = User::where('email', $vehicle->email)->first();
    
      $vehicle->users()->attach([$user->id]);
    }
    

    请理解,BelongsToMany方法实际上没有自己的模型,但对于这样的/一次性情况......您可以尝试制作数据透视表模型,然后处理您的查询。但是,再次,Vehicle::where('license_plate', $val->license_plate)之类的东西可能仍然需要......这又是无用的。

    注意: - 您可以在一个for循环中执行3个查询。或3 for for循环具有多个查询。我肯定更喜欢这里的第一个