2017-04-20 91 views
1

我想優化我的查詢,我正在使用Laravel執行。我爲我的項目使用MySQL,並且我有一個名爲locations的表。它有超過200萬條記錄。 當我執行下面的代碼時,它太慢了。如何優化我的查詢以提高速度?laravel緩慢查詢問題

foreach ($employees as $employee){ 
    $percentage = 0; 
    if ($employee->position->zones->count() > 0) { 
     if($employee->position->zones->first()->workingzones->count() > 0) { 
      $workingZone = $employee->position->zones->first()->workingzones->last(); 
      $tagCode = $employee->rfids->first()->rfid_id; 
      $zoneTime = DB::table('location') 
       ->select(DB::raw('count(*) as count')) 
       ->where('tagCode', $tagCode) 
       ->where('xLocation', '>', $workingZone->x1) 
       ->where('xLocation', '<', $workingZone->x3) 
       ->where('yLocation', '>', $workingZone->y3) 
       ->where('yLocation', '<', $workingZone->y1) 
       ->where('locationDate', '>=',''.$currentDate.' 00:00:01') 
       ->where('locationDate', '<=', $currentDate. ' 23:59:59') 
       ->get(); 


      $totalWorkedTime = DB::table('location') 
       ->select(DB::raw('count(*) as count')) 
       ->where('tagCode', $tagCode) 
       ->where('locationDate', '>=',''.$currentDate.' 00:00:01') 
       ->where('locationDate', '<=', $currentDate. ' 23:59:59')->get(); 


       if ($zoneTime->first()->count == 0 || $totalWorkedTime->first()->count == 0) { 
        $percentage = 0; 
       }else { 
        $percentage = (int)ceil(($zoneTime->first()->count /12)* 100/($totalWorkedTime->first()->count/12)); 
       } 
      } 
     } 

     $employee->percentage = $percentage; 
    } 
+0

使用大塊用於獲取結果 –

+0

還是一樣什麼都沒有改變 –

回答

0

以下列添加索引要提高你的表現:

  • xLocation
  • yLocation
  • locationDate

如何用MySQL查詢添加索引: https://dev.mysql.com/doc/refman/5.7/en/create-index.html

,或者如果您使用Laravel的遷移:https://laravel.com/docs/5.4/migrations#indexes

編輯:

另外:與其做兩個選擇查詢的COUNT(*),使用COUNT(`id`),所以你不要指望所有列,但只有id

+0

我已經添加索引,但它仍然緩慢 –

+0

@MuratKaya你能告訴我什麼樣的數據類型'xLocation'和'yLocation'是誰? –

+0

@MuratKaya還告訴我們更多關於'locationDate'的信息。這可能是一個MySQL日期時間。子字符串搜索可以加快速度。 'where('substr(locationDate,0,10)','<>',$ currentDate)' –

2

您執行完整->get()兩次,只使用->first()結果。當你只需要1時,只需使用->first()而不是->get()。 ( - 分組eagerload查詢總)


您也可以同時獲取員工,並節省2次額外的查詢每圈eagerload的位置和區域,像這樣:

$employees = Employee::where(/*where foo here*/) 
    ->with('position.zones') 
    ->get(); 

而且消耗更少的內存,大塊它。

Employee::where(/*where foo here*/) 
    ->with('position.zones') 
    ->chunk(200, function ($employees) { 
     foreach ($employees as $employee) { 
      // current code here with ->first() instead of ->get() 
     } 
    }); 
+0

這加快了我的查詢,但它仍然很慢得到對象。 –

+0

然後正確的問題是:爲什麼你想在請求中處理2M記錄?假設你這樣做,因爲你說它太慢了。處理一個百分比是你可以在工作中做的事情,你不希望在請求中這樣做這樣的事情...... – Robert

+0

因爲我需要這個記錄中的對象的計數。所以,當我在你的答案後用foreach試用它時,它的速度比第一個版本快,但仍然很慢,我只是試圖更快地計數。 –