性能改进- Yii2主动加载

  • 本文关键字:加载 Yii2 性能 php yii2
  • 更新时间 :
  • 英文 :


我们有一个名为content的表,表的大小超过5Gb。我们的Yii2后端应用程序有一个查看这些内容的部分,并且很少有过滤器可以过滤掉内容。我需要过滤被分配或未分配到类别的内容。

A内容可以在多个类别中共享。因此,在Content表和Category表之间存在一对多的关系。

映射表为content_cat_xref。

模型如下:

内容模型

/**
* @return yiidbActiveQuery
*/
public function getContentCatXrefs()
{
return $this->hasMany(ContentCatXref::className(), ['content_id' => 'id']);
}
<<p>Content_cat_xref模型/strong>
/**
* @return yiidbActiveQuery
*/
public function getCategory()
{
return $this->hasOne(Category::className(), ['id' => 'category_id']);
}
/**
* @return yiidbActiveQuery
*/
public function getContent()
{
return $this->hasOne(Content::className(), ['id' => 'content_id']);
}

控制器

public function actionIndex()
{
$searchModel = new commonmodelsContentSearch();
$dataProvider = $searchModel->searchMedia(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider
]); 
}
<<p>ContentSearch模型/strong>
public function searchMedia($params)
{
$query = Content::find()->where(['file_type_id'=>[1,2,3,4,5,6,8,11]]);

$dataProvider = new ActiveDataProvider([
'query' => $query,
]);

$this->load($params);

if (!$this->validate()) {
return $dataProvider;
}

//Conditionally add filters
if(isset($this->is_category_available) && $this->is_category_available === 'yes'){
$query = $query->joinWith(['contentCatXrefs' => function($queryw){
$queryw->andWhere(['is not', 'content_cat_xref.category_id', new yiidbExpression('null')]);
}]);
}else if(isset($this->is_category_available) && $this->is_category_available === 'no'){
$query = $query->joinWith(['contentCatXrefs' => function($queryw){
$queryw->andWhere(['is', 'content_cat_xref.category_id', new yiidbExpression('null')]);
}]);
}

if(!is_null($this->file_name) && !empty($this->file_name)) {
$query->andWhere("MATCH (file_name) AGAINST ("".$this->file_name."" IN NATURAL LANGUAGE MODE)");
}

if(!is_null($this->file_path) && !empty($this->file_path)) {
$query->andWhere("MATCH (file_path) AGAINST ("".$this->file_path."" IN NATURAL LANGUAGE MODE)");
}

$query->andFilterWhere(['type_code'=>$this->type_code]);
$query->andFilterWhere(['file_type_id'=>$this->file_type_id]);
$query->andFilterWhere(['content.active_status'=>$this->active_status]);
$query->andFilterWhere(['content.content_status'=>$this->content_status]);

if(is_null($this->file_name)) {
$query->orderBy("id desc");
}
return $dataProvider;
}

我有几个问题

  1. 连接两个表(content和content_cat_xref)来检索数据的正确和有效的方法应该是什么?我需要过滤分配或不分配给类别的内容。因此,我使用这个过滤器

    if(isset($this->is_category_available) && $this->is_category_available === 'yes'){
    $query = $query->joinWith(['contentCatXrefs' => function($queryw){
    $queryw->andWhere(['is not', 'content_cat_xref.category_id', new yiidbExpression('null')]);
    }]);
    }else if(isset($this->is_category_available) && $this->is_category_available === 'no'){
    $query = $query->joinWith(['contentCatXrefs' => function($queryw){
    $queryw->andWhere(['is', 'content_cat_xref.category_id', new yiidbExpression('null')]);
    }]);
    }
    
  2. 我在这里使用急切加载来提高性能。但是当连接这两个表时,它会给出重复的记录。在我使用distinct之后,它会降低性能。正确的做法应该是什么?

  3. 在内容搜索模型中构建查询时,是否有方法将参数传递给关系函数?

  4. 如果我们按id降序排序内容,再次降低性能。

如果有人能提供指导,我将不胜感激。

  1. 如果目标是过滤分配或未分配到类别的内容,我建议在"content"中保留一个标志;表格或者,您可以在现有表中添加索引,以提高连接和条件的性能,但它总是比单个表上标记字段上的条件慢。你可以用&;explain&;语句,以获取所使用索引的信息,并且它将有助于您添加新索引
  2. 问题不在于Yii2,而是记录是否保留在表中。如果在"content_cat_xref"中有多个条目表中从"内容"表,那么您的联接将返回多个记录,其中记录来自"content"表将是相同的各自的行,但记录从"content_cat_xref"每一行都是不同的。解决方案是使用子查询(将影响性能)或维护第1点
  3. 中解释的标志。
  4. 在Yii2中,根据模型类中的方法返回形成关系。你可以在这些方法中写条件。例如:
if($this->is_category_available == 'yes') {
return $this->hasMany(ContentCatXref::className(), ['content_id' => 'id'])
->andOnCondition(['a_type' => 1]);
}
else  {
return $this->hasMany(ContentCatXref::className(), ['content_id' => 'id'])
->andOnCondition(['a_type' => 0]);
}
  1. 添加索引

最新更新