为什么Laravel不会自动优化模型查询?

时间:2016-03-30 17:58:18

标签: mysql laravel doctrine query-builder rdms

直到今天我依赖于Laravel的关系,但自从我打开mysql日志后我非常失望。

当我执行代码

Company::with(['users', 'machines'])->get()

mysql.log看起来就是这样

select * from `company` where `company`.`id` = '48' limit 1
select * from `user` where `user`.`company_id` in ('48')
select * from `machine` where `machine`.`company_id` in ('48')

为什么Laravel不使用连接进行急切提取?另外,有没有什么方法可以提高性能并仍然使用Laravel模型?

我知道通过使用连接,Doctrine ORM eager loading非常好用。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

如果你真的想使用连接而不是Eloquent计算查询,我想你可以使用流畅的查询构建器(通过数据库外观随Laravel一起提供)并将该代码粘贴到模型的方法中一切都很好和SRP。

例如:

function

这将为您生成正确的连接查询。

至于为什么要这样做,您必须对这两个选项进行基准测试,以确定哪个选项可以为您的特定数据提供最佳性能。我不会一概而论,一种选择总是比另一种更好/更差。

答案 1 :(得分:1)

正如评论中所述,我不确定性能方面为什么这是首选方法,但是从可用性来看,能够访问模型的关系,因为它拥有独立的属性比使用join要容易得多,尤其是在many-to-one关系的情况下。

让我们使用->with()->leftJoin()方法比较上述示例。

使用->with()时,每个关系都被定义为Company的属性,可通过$company->users访问。在此属性foreach()上运行foreach($company->users AS $user)循环并输出信息很容易,例如usernameemail等。另外,如果{{1}没有Company,您不必担心显示空值(对于使用users表示法链接模型尤其重要,例如.)。

现在,看users.user_details。如果您尝试在每个模型及其子模型上链接多个leftJoin(),那么您很有可能无法获得您期望的结果。从本质上讲,leftJoins()不会处理leftJoin()个记录以及个别查询。

接下来,要输出公司用户的列表,您必须运行循环,例如:

NULL

由于foreach($company AS $row){ echo $row->username; echo $row->email; // etc etc } 根本无法处理重复的属性,因此会出现问题。例如,如果公司有Eloquent字段以及用户,那么任何人都可以猜测实际显示的是哪个字段。除非您执行email,否则将只返回一个selectRaw("companies.email AS email, users.email AS user_email)"属性。这也适用于像email这样的列,其中多个将使用id获取,但实际上只有一个可以访问。

长话短说,leftJoin()在尝试连接多个表时可能存在大量问题,可能存在重复信息,空信息等。同时使用{{运行多个查询的性能1}}方法可能不是最好的,它允许更容易地用于检索和显示信息。