Sli*_*liq 13 php mysql orm activerecord yii2
根据文档,我正在使用Yii2的ActiveRecord实现(希望)完全按照应该使用的方式.
在一个非常简单的设置中,表之间有简单的关系,获取10个结果很快,100个很慢.1000是不可能的.数据库非常小,索引完美.问题绝对是Yii2请求数据的方式,而不是数据库本身.
我正在使用标准的ActiveDataProvider,如:
$provider = new ActiveDataProvider([
'query' => Post::find(),
'pagination' => false // to get all records
]);
Run Code Online (Sandbox Code Playgroud)
使用Yii2工具栏进行调试显示数以千计的单个SELECT,用于一个简单的请求,它应该从表A获得50行,一些简单的"JOIN"到表B到表C.在普通的SQL中,每个人都会用一个SQL语句和两个连接来解决这个问题. .然而,Yii2为每一行中的每个关系激活一个SELECT(这对于保持ORM清洁是有意义的).导致(或多或少)1*50*30 = 1500个查询,只获得每行的两个关系.
为什么Yii2使用这么多单一的SELECT,或者这是我的错误?另外,有人知道如何"修复"这个吗?
由于这对我来说是一个非常重要的问题,我将在5月14日提供500赏金.
top*_*her 24
默认情况下,Yii2使用延迟加载以获得更好的性能.这样做的结果是只有在访问它时才会获取任何关系,因此成千上万的sql查询.您需要使用预先加载.你可以这样做\yii\db\ActiveQuery::with():
指定应执行此查询的关系
说你的关系是comments,解决方案如下:
'query' => Post::find()->with('comments'),
Run Code Online (Sandbox Code Playgroud)
从关系指南,with将执行额外的查询以获得关系,即:
SELECT * FROM `post`;
SELECT * FROM `comment` WHERE `postid` IN (....);
Run Code Online (Sandbox Code Playgroud)
要使用适当的加入,使用joinWith与eagerLoading设定参数true,而不是:
此方法允许您重用现有关系定义来执行JOIN查询.根据指定关系的定义,该方法将一个或多个JOIN语句附加到当前查询.
所以
'query' => Post::find()->joinWith('comments', true);
Run Code Online (Sandbox Code Playgroud)
将导致以下查询:
SELECT `post`.* FROM `post` LEFT JOIN `comment` comments ON post.`id` = comments.`post_id`;
SELECT * FROM `comment` WHERE `postid` IN (....);
Run Code Online (Sandbox Code Playgroud)
来自@ laslov的评论和https://github.com/yiisoft/yii2/issues/2379
重要的是要意识到使用
joinWith()不会使用JOIN查询来急切加载相关数据.由于各种原因,即使使用JOIN,WHERE postid IN (...)仍将执行查询以处理急切加载.因此,您应该仅joinWith()在特别需要JOIN时使用,例如,在相关表的列之一上过滤或排序
TLDR:
joinWith= with加上实际的JOIN(因此能够通过其中一个相关列过滤/订购/分组等)
| 归档时间: |
|
| 查看次数: |
2466 次 |
| 最近记录: |