我有一个包含10000个用户的表,并且与work_hours
表有关系。
这是我的用户模型以及如何获得工时总和。
protected $appends = ['sum_work_hours'];
public function work_hours()
{
return $this->hasMany(WorkHour::class);
}
public function getSumWorkHoursAttribute()
{
return $this->work_hours->sum('hours_total');
}
我查询了所有用户及其工作时间总和,如下所示:
public function getHoursDatatable()
{
$users = User::with('work_hours')->get();
return Datatables::of($users)->make();
}
此查询需要 7-8秒才能显示非常慢的表格。
我知道这是因为总结了work_hours
表中每个用户的总工作时间,我想学习如何在考虑数据量的情况下优化此查询?
$users = User::with('work_hours')->select(['users.name', 'users.email']);
return Datatables::of($users)
->add_column('sum_work_hours', function(User $user) {
return $user->work_hours->sum('hours_total');
})
->make();
这给了我一个错误:
DataTables警告:table id = users-table - Ajax错误。更多 有关此错误的信息,请参阅http://datatables.net/tn/7
这有效:
public function getHoursDatatable()
{
$users = User::with('work_hours');
return Datatables::of($users)
->addColumn('sum_work_hours', function(User $user) {
return $user->work_hours->sum('hours_total');
})
->make();
}
但也需要 7-8秒来加载......
答案 0 :(得分:1)
在某些时候,您的数据会变得太大,无法一次查询所有内容。
基本上你有两个选择:
1。
既然你已经拥有10K用户(并且这个数字可能还会增长?)我建议切换到异步(serverSide: true
选项)。您正在使用数据表,因此显然您不需要1页中的所有10K用户,也不需要所有这些用户来处理单个报告。
数据表确实允许服务器端处理,它确实允许分页,同时保留过滤和排序的选项,就像你现在可能正在做的那样。
yajra包将继续做它现在正在做的事情,你必须改变的是你没有将所有用户分配到视图并像这样构建它,你需要一个emtpy表并让它前端填充它。只需创建一个api端点,您可以在其中指向数据表,以便从中获取分页列表。
因此,不要在视图中使用@foreach ($users as $user)
,不要在显示表的控制器操作中获取它,让api端点处理它。
示例:
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Total Hours</th>
</tr>
</thead>
<tfoot>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Total Hours</th>
</tr>
</tfoot>
</table>
你需要这样做(这里或你正在使用的某些文库)
$(document).ready(function() {
$('#example').DataTable( {
"processing": true,
"serverSide": true,
"ajax": "../server_side/scripts/server_processing.php"
} );
} );
您还需要:
// code.jquery.com/jquery-1.12.4.js https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js
如果您尚未在项目中包含该项目,那么您的信息就不清楚了。
有关详细信息,请参阅:Datatables Server-side processing
2。 在其他地方存储总小时数。您可以在完成对Workhour模型的更改时更新每个用户的小时数。这样,每次请求单个或列表(或所有)用户时,您都不需要进行总和。
我的建议是至少做#1和#2将是一个很好的优化之后。