laravel慢查询问题

时间:2017-04-20 11:12:47

标签: php mysql laravel laravel-5

我想优化我的查询,我正在使用Laravel执行。我正在为我的项目使用MySQL,我有一个名为locations的表。它有超过200万条记录。 当我执行下面的代码时,它太慢了。如何优化查询以提高速度?

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

2 个答案:

答案 0 :(得分:2)

您执行完整->get()两次,仅使用->first()结果。当您只需要1时,只需使用->first()代替->get()

此外,您可以在获取员工时加载位置和区域,并为每个循环保存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()
        }
    });

答案 1 :(得分: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