Activerecord Yi2 hasMany/via vs.hasMany/viaTable vs.find/joinWith

Activerecord Yi2 hasMany/via vs.hasMany/viaTable vs.find/joinWith,activerecord,yii2,relation,Activerecord,Yii2,Relation,我在Yii2中有一个多对多关系:接受单位重量成分。在RecipeUnit型号中: public function getIngredientWeights() { return $this->hasMany(IngredientWeight::className(), ['recipe_unit_id' => 'id']); } public function getIngredients() { return $this->hasMany(Ingredien

我在Yii2中有一个多对多关系:接受单位重量成分。在RecipeUnit型号中:

public function getIngredientWeights()
{
    return $this->hasMany(IngredientWeight::className(), ['recipe_unit_id' => 'id']);
}

public function getIngredients()
{
    return $this->hasMany(Ingredient::className(), ['id' => 'ingredient_id'])
                ->via('ingredientWeights');
}
使用以下代码ActiveQuery生成两个SQL而不是一个联接,并且需要很长时间(
$model
是一个id为
id
=4的RecipeUnit实例):

如果我使用
hasMany
/
viaTable
而不是
hasMany
/
via
,结果是一样的:

public function getIngredients()
{
    return $this->hasMany(Ingredient::className(), ['id' => 'ingredient_id'])
                ->viaTable(IngredientWeight::tableName(), ['recipe_unit_id' => 'id']);
}
但如果没有HASSANY,则会生成一个正常连接,运行速度非常快:

public function getIngredients()
{
    return Ingredient::find()->joinWith(['ingredientWeights'])->where([
            '{{%ingredient_weight}}.recipe_unit_id' => $this->id]);
}

SELECT `dh_ingredient`.* FROM `dh_ingredient`
    LEFT JOIN`dh_ingredient_weight`
    ON `dh_ingredient`.`id` = `dh_ingredient_weight`.`ingredient_id`
WHERE `dh_ingredient_weight`.recipe_unit_id=4
ORDER BY `sort_order` LIMIT 1 (1 record 0.2 ms)

问题是,如果将关系定义为上一个示例中的关系,而不使用
hasMany
/
via

我在Yii2中有一个多对多关系:RecipeUnit-IngCrediteWeight-Component
您编写的,并且您的联接是简单的
hasMany
关系,那么会有什么缺点吗。所以是的,当然会更快。同样,在第二种情况下,您使用的是
limit1
,在第一种情况下,相同的查询get的
2977
结果。做你的测试是正确的。有时,使用
IN()
连接比加载记录更有效。我认为,如果两个模型(RecipeUnit和Component)之间存在切换模型(在本例中为IngredientWeight),则这是一种
真实的N对N关系。通过
方法正好实现了这一点。
public function getIngredients()
{
    return Ingredient::find()->joinWith(['ingredientWeights'])->where([
            '{{%ingredient_weight}}.recipe_unit_id' => $this->id]);
}

SELECT `dh_ingredient`.* FROM `dh_ingredient`
    LEFT JOIN`dh_ingredient_weight`
    ON `dh_ingredient`.`id` = `dh_ingredient_weight`.`ingredient_id`
WHERE `dh_ingredient_weight`.recipe_unit_id=4
ORDER BY `sort_order` LIMIT 1 (1 record 0.2 ms)