簡體   English   中英

性能提升 - Yii2 急切加載

[英]Performance improvement - Yii2 Eager loading

我們有一個名為 content 的表,表的大小超過 5Gb。 我們的 Yii2 后端應用程序有一個部分可以查看這些內容,並且幾乎沒有過濾器可用於過濾掉內容。 我需要過濾已分配或未分配給類別的內容。

關系

內容可以在許多類別中共享。 因此 Content 和 Category 表之間存在一對多的關系。

映射表是 content_cat_xref。

型號如下。

內容 model

 /**
 * @return \yii\db\ActiveQuery
 */
public function getContentCatXrefs()
{
    return $this->hasMany(ContentCatXref::className(), ['content_id' => 'id']);
}

Content_cat_xref model

/**
 * @return \yii\db\ActiveQuery
 */
public function getCategory()
{
    return $this->hasOne(Category::className(), ['id' => 'category_id']);
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getContent()
{
    return $this->hasOne(Content::className(), ['id' => 'content_id']);
}

Controller

 public function actionIndex()
{
    $searchModel = new \common\models\ContentSearch();
    $dataProvider = $searchModel->searchMedia(Yii::$app->request->queryParams);
    return $this->render('index', [
        'searchModel' => $searchModel,
        'dataProvider' => $dataProvider
    ]); 
}

內容搜索 Model

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 \yii\db\Expression('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 \yii\db\Expression('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 \yii\db\Expression('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 \yii\db\Expression('null')]); }]); }
  2. 我在這里使用急切加載來提高性能。 但是在加入這兩個表時它會給出重復的記錄。 在我使用 distinct 之后,它會降低性能。 執行此 Yii2 的正確方法應該是什么?

  3. 在內容搜索 model 中構造查詢時,有沒有辦法將參數傳遞給關系函數?

  4. 如果我們按 id 降序排列內容,再次降低性能。

如果有人可以提供這方面的指導,我們將不勝感激。

  1. 如果目標是過濾分配或未分配給類別的內容,我建議在“內容”表中維護一個標志。 或者您可以在現有表中添加索引以提高連接和條件的性能,但它總是比單個表上的標志字段上的條件慢。 您可以使用“解釋”語句來獲取有關使用的索引的信息,這也將有助於您添加新索引
  2. 問題不在於 Yii2,而是記錄會保留在表中。 如果“content”表中的相應行在“content_cat_xref”表中有多個條目,那么您的聯接將返回多條記錄,其中“content”表中的記錄對於相應的行將相同,但“content_cat_xref”中的記錄將不同對於每一行。 解決方案是使用子查詢(會影響性能)或維護標志,如第 1 點所述
  3. 在 Yii2 中,基於 model class 中的方法返回形成關系。 您可以在該方法中編寫條件。 例如:
 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. 在表中添加索引

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM