Laravel-收集关系需要花费大量时间
我们正在开发一种带有流明的API。 今天,我们在获取“TimeLog”模型集合时遇到了一个困惑的问题。 我们只是想从board模型和task模型中获取所有时间日志和附加信息。 在一行时间日志中,我们有一个board_id和一个task_id。这两者都是1:1的关系 这是我们获取全部数据的第一个代码。这花费了很多时间,有时我们会超时: BillingController.phpLaravel-收集关系需要花费大量时间,laravel,laravel-5.4,lumen,lumen-5.4,Laravel,Laravel 5.4,Lumen,Lumen 5.4,我们正在开发一种带有流明的API。 今天,我们在获取“TimeLog”模型集合时遇到了一个困惑的问题。 我们只是想从board模型和task模型中获取所有时间日志和附加信息。 在一行时间日志中,我们有一个board_id和一个task_id。这两者都是1:1的关系 这是我们获取全部数据的第一个代码。这花费了很多时间,有时我们会超时: BillingController.php public function byYear() { $timeLog = TimeLog::get()
public function byYear() {
$timeLog = TimeLog::get();
$resp = array();
foreach($timeLog->toArray() as $key => $value) {
if(($timeLog[$key]->board_id && $timeLog[$key]->task_id) > 0 ) {
array_push($resp, array(
'board_title' => isset($timeLog[$key]->board->title) ? $timeLog[$key]->board->title : null,
'task_title' => isset($timeLog[$key]->task->title) ? $timeLog[$key]->task->title : null,
'id' => $timeLog[$key]->id
));
}
}
return response()->json($resp);
}
public function byYear() {
$timeLog = TimeLog::
join('oc_boards', 'oc_boards.id', '=', 'oc_time_logs.board_id')
->join('oc_tasks', 'oc_tasks.id', '=', 'oc_time_logs.task_id')
->join('oc_users', 'oc_users.id', '=', 'oc_time_logs.user_id')
->select('oc_boards.title AS board_title', 'oc_tasks.title AS task_title','oc_time_logs.id','oc_time_logs.time_used_sec','oc_users.id AS user_id')
->getQuery()
->get();
return response()->json($timeLog);
}
建立关系的TimeLog.php
public function board()
{
return $this->belongsTo('App\Board', 'board_id', 'id');
}
public function task()
{
return $this->belongsTo('App\Task', 'task_id', 'id');
}
我们的新方式是这样的:
BillingController.php
public function byYear() {
$timeLog = TimeLog::get();
$resp = array();
foreach($timeLog->toArray() as $key => $value) {
if(($timeLog[$key]->board_id && $timeLog[$key]->task_id) > 0 ) {
array_push($resp, array(
'board_title' => isset($timeLog[$key]->board->title) ? $timeLog[$key]->board->title : null,
'task_title' => isset($timeLog[$key]->task->title) ? $timeLog[$key]->task->title : null,
'id' => $timeLog[$key]->id
));
}
}
return response()->json($resp);
}
public function byYear() {
$timeLog = TimeLog::
join('oc_boards', 'oc_boards.id', '=', 'oc_time_logs.board_id')
->join('oc_tasks', 'oc_tasks.id', '=', 'oc_time_logs.task_id')
->join('oc_users', 'oc_users.id', '=', 'oc_time_logs.user_id')
->select('oc_boards.title AS board_title', 'oc_tasks.title AS task_title','oc_time_logs.id','oc_time_logs.time_used_sec','oc_users.id AS user_id')
->getQuery()
->get();
return response()->json($timeLog);
}
我们删除了TimeLog.php中的关系,因为我们不再需要它了。现在我们有大约1秒的加载时间,这很好!
时间日志表中大约有20k个条目
我的问题是:
如果你需要更多的信息,就问我 我也遇到过类似的问题。这里的主要问题是,Elloquent执行大量任务的速度非常慢,因为它会同时获取所有结果,因此简单的答案是使用PDO fetch逐行获取它 简短示例:
$db = DB::connection()->getPdo();
$query_sql = TimeLog::join('oc_boards', 'oc_boards.id', '=', 'oc_time_logs.board_id')
->join('oc_tasks', 'oc_tasks.id', '=', 'oc_time_logs.task_id')
->join('oc_users', 'oc_users.id', '=', 'oc_time_logs.user_id')
->select('oc_boards.title AS board_title', 'oc_tasks.title AS task_title','oc_time_logs.id','oc_time_logs.time_used_sec','oc_users.id AS user_id')
->toSql();
$query = $db->prepare($query->sql);
$query->execute();
$logs = array();
while ($log = $query->fetch()) {
$log_filled = new TimeLog();
//fill your model and push it into an array to parse it to json in future
array_push($logs,$log_filled);
}
return response()->json($logs);
我也遇到过类似的问题。这里的主要问题是,Elloquent执行大量任务的速度非常慢,因为它会同时获取所有结果,因此简单的答案是使用PDO fetch逐行获取它 简短示例:
$db = DB::connection()->getPdo();
$query_sql = TimeLog::join('oc_boards', 'oc_boards.id', '=', 'oc_time_logs.board_id')
->join('oc_tasks', 'oc_tasks.id', '=', 'oc_time_logs.task_id')
->join('oc_users', 'oc_users.id', '=', 'oc_time_logs.user_id')
->select('oc_boards.title AS board_title', 'oc_tasks.title AS task_title','oc_time_logs.id','oc_time_logs.time_used_sec','oc_users.id AS user_id')
->toSql();
$query = $db->prepare($query->sql);
$query->execute();
$logs = array();
while ($log = $query->fetch()) {
$log_filled = new TimeLog();
//fill your model and push it into an array to parse it to json in future
array_push($logs,$log_filled);
}
return response()->json($logs);
--第一个问题--
您可能面临的一个问题是内存中存在大量数据,即:
$timeLog = TimeLog::get();
这已经是巨大的。然后,当您尝试将集合转换为数组时:
$timeLog->toArray()
效率不高(不过我可能对此并不完全正确)chunk
结果ref:因此您有以下内容:
$timeLog = TimeLog::chunk(1000, function($logs){
foreach ($logs as $log) {
// Do the stuff here
}
});
TimeLog::where([['board_id','>',0],['task_id', '>', 0]])->get()
- 使用transformer,您可以以优雅、干净和更可控的方式加载相关模型,即使大小巨大,一个更大的好处是您可以转换结果,而不必担心如何循环 您可以简单地引用,以便对其进行简单的使用。然而,如果你不需要改变你的反应,那么你可以采取其他的选择
光标
,但不确定。最后,我想这可能更理想,因为:
return TimeLog::paginate(1000);
--第一个问题--
您可能面临的一个问题是内存中存在大量数据,即:
$timeLog = TimeLog::get();
这已经是巨大的。然后,当您尝试将集合转换为数组时:
$timeLog->toArray()
效率不高(不过我可能对此并不完全正确)chunk
结果ref:因此您有以下内容:
$timeLog = TimeLog::chunk(1000, function($logs){
foreach ($logs as $log) {
// Do the stuff here
}
});
TimeLog::where([['board_id','>',0],['task_id', '>', 0]])->get()
- 使用transformer,您可以以优雅、干净和更可控的方式加载相关模型,即使大小巨大,一个更大的好处是您可以转换结果,而不必担心如何循环 您可以简单地引用,以便对其进行简单的使用。然而,如果你不需要改变你的反应,那么你可以采取其他的选择