【发布时间】:2019-02-26 09:35:12
【问题描述】:
我已经使用 Laravel 构建了一个应用程序,我最终在其中建立了相当深的嵌套关系,有时我需要查询这些关系。数据库是 MySQL。
例如,我想检索所有允许阅读书籍的用户。我的数据结构如下:
- 一个 User 通过一个 UserMembership 属于 0-n 个 UserGroups
- 一个用户组有0-n个权限
- 权利与 1 书相关,并描述了可以执行的操作
查看浏览后发现有人推荐如下解决嵌套关系的方法:
// class Book extends Model
public function readers() {
$bookId= $this->id;
return User::whereHas('memberships', function($m) use($bookId) {
$m->whereHas('group', function($g) use($bookId) {
$g->whereHas('rights', function($r) use($bookId) {
$r->where('resource_id', $bookId)->where('action', 'read');
});
});
});
}
我喜欢这段代码很有意义,但性能很糟糕。Book::find(967)->readers()->get()的平均执行时间为 430ms
我重写了函数如下:
public function readersNew() {
$bookId= $this->id;
$g = Right::where('resource_id', $bookId)->where('action', 'read')->pluck('group_id');
$uIds = UserMembership::whereIn('group_id', $g)->pluck('user_id');
return User::whereIn('id', $uIds);
}
使用这段代码,我实现了 4ms 的平均执行时间,这显然要好得多。但这在编写嵌套请求方面看起来也不那么“有条理”。
我真的很想了解:
- 为什么 readers()->get() 比 readersNew()->get() 慢很多
- 最好的方法是编写此类请求
【问题讨论】:
-
既然“最佳方式”确实是由生成的SQL决定的,请给我们看看。
标签: mysql laravel performance eloquent