我需要将大量数据批量插入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完成循环项目。
答案 0 :(得分:1)
首先,加载所有用户。但只选择id
和email
:
$users = User::pluck('email', 'id')->toArray();
这将创建一个[id => email]
结构的数组。
然后,您将能够使用此数组而无需执行其他查询:
$userId = $users[$email];
然后将id
类型的bigint
列添加到vehicle_user
数据透视表。为此表创建单独的块数组,并使用批量插入关系而不是使用attach()
方法。
答案 1 :(得分:0)
首先,请理解您所遵循的技术是让您一次又一次地遍历$data
(实际上非常大)。为什么?因为...
$user->vehicles()->sync([...Vehicle Ids...]);
通过只为一个循环制作一个循环,您可以通过
简单地完成任务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循环具有多个查询。我肯定更喜欢这里的第一个。