该不该使用Laravel的关联模型

Laravel提供了强大的关联模型功能,关联模型是Eloquent ORM的核心功能,为了让用户更好地使用该功能,Laravel专门为他的关联模型写了一篇详细的文档。那么关联模型提供了这么方便的功能,他到底好不好呢?

众所周知,关联模型就是帮助你方便的找到一张数据表的记录在另外一张表中与之相关的记录。

举个例子,下面是你的两张数据表:

users用户表

idnickname
1Tony
2Pony
3Jack

comments评论表

idpost_iduser_idcontent
111hello
222world
333hello world

那么在你的Comment Model中一定有这样一段代码:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * 获取评论对应的用户信息
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

这时候你就可以在其他地方使用关联模型了:

foreach($comments as $comment) {
    // 获取此条评论的用户昵称
    echo $comment->user->nickname;
}

而这会有什么问题呢?Laravel关联模型的原理是用户在Model中建立关联关系,就是上面的user()方法,方法里面的内容是告诉Laravel评论表里的user_id字段和用户表中的id字段是对应的,当$comment->user->nickname执行的时候,程序就会通过$comment->user_id去用户表找到对应id的记录然后返回name字段的值。

那么问题来了,也就是说,你每执行一次$comment->user->nickname,程序就会去查一次数据库,数据库查询次数与foreach总共遍历次数是相同的。如果用户表有2000万条记录,那么这么多次查询显然是难以接受的,这时候取出所有的$comment->user_id然后进行一次whereIn查询显然更合适,只是需要自己去做对应的逻辑了,但这对效率的提升是值得的。

如果你想监控查看关联模型对数据库的调用,可以在app/Providers/AppServiceProvider.php的boot方法中加一段代码:

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    DB::listen(function($query) {
        $sql = $query->sql;
        $i = 0;
        while (true) {
            if (!$position = strpos($sql, '?')) {
                break;
            }

            $prefix = substr($sql, 0, $position) . $query->bindings[$i];
            $subfix = substr($sql, $position + 1);

            $sql = $prefix . $subfix;
            $i++;
        }
        Log::debug($sql);
    });
}

这样就可以通过日志查看Laravel每次执行的SQL语句了,从而可以清晰地看到关联模型的数据库查询次数。

总结

当你在做一些小数据量的快速开发时,使用Laravel提供的关联模型无疑是最方便的,但是如果你的数据量较大,使用Laravel的关联模型将会耗费较多资源多次查询数据库,程序的响应速度会明显变慢很多。

发表评论

电子邮件地址不会被公开。 必填项已用*标注