laravel如何减少查询计数,急切负载?

时间:2017-03-30 17:06:09

标签: php mysql laravel eloquent

说我有3个模特

  • Users
  • Attendees
  • ScheduleProgramSegments

Attendees属于Users

  • User hasMany Attendees

Bookings是一种枢轴关系

  • Attendees belongsToMany ScheduledProgramSegments(数据透视表= bookings

我得到了枢轴关系的计数,我有大约600个查询,因为它不断查询每个scheduled_program_segment_id的计数...我不知道如何在一个查询中得到它们。 .eager load或其他。

正在运行的查询(由调试栏显示)

select * from `scheduled_program_segments` where `scheduled_program_segments`.`scheduled_program_id` = '477'410μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1392' and `bookings`.`registered` = '1'450μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1392' and `bookings`.`registered` = '1'390μs
select * from `scheduled_program_segments` where `scheduled_program_segments`.`scheduled_program_id` = '478'420μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1393' and `bookings`.`registered` = '1'390μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1393' and `bookings`.`registered` = '1'390μs
select * from `program_sessions` where `program_sessions`.`id` = '23' limit 1390μs
select * from `scheduled_program_segments` where `scheduled_program_segments`.`scheduled_program_id` = '478'450μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1393' and `bookings`.`registered` = '1'390μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1393' and `bookings`.`registered` = '1'380μs
select * from `scheduled_program_segments` where `scheduled_program_segments`.`scheduled_program_id` = '481'730μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1396' and `bookings`.`registered` = '1'400μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1396' and `bookings`.`registered` = '1'390μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1397' and `bookings`.`registered` = '1'390μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1398' and `bookings`.`registered` = '1'390μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1399' and `bookings`.`registered` = '1'390μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1400' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1401' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1402' and `bookings`.`registered` = '1'440μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1403' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1404' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1405' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1406' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1407' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1408' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1409' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1410' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1411' and `bookings`.`registered` = '1'380μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1412' and `bookings`.`registered` = '1'430μs
select count(*) as aggregate from `attendees` inner join `bookings` on `attendees`.`id` = `bookings`.`attendee_id` where `bookings`.`scheduled_program_segment_id` = '1413' and `bookings`.`registered` = '1'

修改

在控制器中急切加载

$programs = ScheduledProgram::with('scheduledProgramSegments.registeredAttendees','scheduledProgramSegments.attendees')->where('registration_start_date', '<=', $today)
                            ->where('end_date',                '>=',  $today)
                            ->get();

$user->load('attendees', 'attendees.scheduledProgramSegments')->get();



return View::make('user/registration/edit', compact('user','programs'));

预定程序模型

     public function scheduledProgramSegments()
  {
    return $this->hasMany('ScheduledProgramSegment');
  }
  public function program()
  {
    return $this->belongsTo('Program');
  }
  public function programSession()
  {
    return $this->belongsTo('ProgramSession');
  }
  public function attendees()
  {
    return $this->belongsToMany('Attendee', 'prog_bookings')->withPivot('registered','paid')->withTimestamps();
    //return $this->hasManyThrough('Attendee', 'ScheduledProgramSegment','id','id' );
  }

  public function registeredAttendees()
  {
      //return $this->scheduledProgramSegments->attendees()->wherePivot('registered', 1);
      return $this->attendees()->wherePivot('registered', 1);
  }
  public function getRegisteredCountAttribute()
  {
    //return $this->registeredAttendees->count();
    //Consider changing this to calculate the max registered of the child programs
    $largest = 0;
    $segments = $this->scheduledProgramSegments()->get();
//return $segments->first()->registered_count;
    foreach($segments as $segment){
      $largest = ($segment->registered_count > $largest) ? $segment->registered_count : $largest;
    }
    return $largest;
  }

参加者模型

public function user()
{
    return $this->belongsTo('User');
}

public function scheduledProgramSegments()
{
    return $this->belongsToMany('ScheduledProgramSegment', 'bookings')->withPivot('paid','registered')->withTimestamps();
}

查看

  <td class="cap">{{{$program->registered_count . '/' . $program->max_attendees}}}</td>

1 个答案:

答案 0 :(得分:1)

将getRegisteredCountAttribute函数更改为

 public function getRegisteredCountAttribute()
 {
      //return $this->registeredAttendees->count();
      //Consider changing this to calculate the max registered of the child programs
      $largest = 0;
      $segments = $this->with('scheduledProgramSegments')->get(); // this is the line to change. this will prevent the N+1 query problem.

      //return $segments->first()->registered_count;
      foreach($segments as $segment){
           $largest = ($segment->registered_count > $largest) ? $segment->registered_count : $largest;
      }

      return $largest;

}

这也是

 public function registeredAttendees()
 {
    //return $this->scheduledProgramSegments->attendees()->wherePivot('registered', 1);
    return $this->with('attendees')->wherePivot('registered', 1);
 }