2016-12-17 61 views
1

我需要批量插入大量的數據到MySQL。大約50萬行,在Laravel關係(硬部分)5.3Laravel 5批量插入與關係

表是車輛,用戶和user_vehicle

普通車輛插入陣列看起來是這樣的:

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

    array_push($vehicles, $temp); 
} 

我可以成功地插入記錄等這:

$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 
} 

我需要運行他們在大塊(10K在我的情況)因爲1 1插入需要太長時間

// 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]); 
} 

我怎樣才能批量插入車輛他們的關係?

編輯:慢部分正在做數據庫查詢。我可以等10-20秒完成循環的項目。

回答

1

首先,加載所有用戶。但只選擇idemail

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

這將創建一個陣列[id => email]結構。

然後你就可以不執行額外的查詢與該陣列的工作:

$userId = $users[$email]; 

然後bigint類型的id列添加到vehicle_user透視表。爲此表創建單獨的塊數組,並使用批量插入關係而不是使用attach()方法。

+0

感謝您的第一部分代碼。它真的讓事情更快=)並直接添加到vehicle_user與DB ::插入(bulk_data)的作品。只需要弄清楚如何從首次批量插入中獲取車輛ID。 –

0

首先,請理解你所關注的技術是讓你循環遍歷$data(真的很大)。爲什麼?因爲...

  1. 首先用於製作臨時變量的循環。
  2. 然後第二個for循環插入分塊數據。
  3. 三for循環使用相同的電子郵件作爲輸入查找用戶,然後選擇同一用戶的車輛,然後安裝與$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用於多個查詢的循環。我肯定會喜歡這裏的第一個

+0

** 1)**運行第一個循環大約需要5-10秒, ** 2)**插入分塊數據只需要幾秒鐘 運行數據庫查詢確實很慢。雖然循環插入它們大約需要20分鐘。在循環到變量之前保存所有用戶的速度要快於從數據庫中爲每個循環詢問它們。認爲我必須在這裏使用原始的sql:/ –

+0

@ MargusKevin你試過我的答案嗎? – prateekkathal

+1

是的,它運行了15分鐘,並以超時結束 –