2014-08-31 102 views
1

我在MySQLMySQL的插入,如果不更新

wi_indv_training(trn_id,ind_id,is_deleted) 
wi_trn_org(trn_id,grp_id,is_deleted) 
wi_indv_org(ind_id,grp_id,is_deleted) 

這裏三個表,多組可以被分配到由wi_trn_org表處理的培訓。 多個人可以分配到多個組。許多個人都參與培訓。在這裏,我們提供的個人已經與團體相關聯。 現在在插入一個組進行訓練時,該組中的個人必須與訓練相關聯。在給定的訓練中可能已經有is_deleted = yes標記的組和個人(部分或全部)。

現在,在插入時,我想用is_deleted = no標記已刪除的組和個人,如果數據已經存在於相應的表中,則應該將數據作爲新數據插入。爲此,我實施了以下性能非常緩慢的方法;

foreach ($grp_id as $key => $value) { 
    # code... 
    $rs=$this->db->pdoQuery("SELECT * FROM wi_trn_org 
          WHERE trn_id='$trn_id' 
          AND grp_id='$value'")->results();    
    if(count($rs)>0) 
    { 
     $this->db->pdoQuery("UPDATE wi_trn_org SET is_deleted=0 
          WHERE trn_id='$trn_id' AND grp_id='$value'"); 
     $grp_indv=$this->db->pdoQuery("SELECT ind_id 
             FROM wi_indv_org 
             WHERE grp_id='$value' 
             AND is_deleted=0")->results(); 
     foreach ($grp_indv as $ke => $va) 
     { 
      $ind_id=$va['ind_id']; 
      $rows=$this->db->pdoQuery("SELECT * FROM wi_indv_training 
             WHERE trn_id='$trn_id' 
             AND ind_id='$ind_id'")->results(); 
      if(count($rows)>0) 
      { 
       $this->db->pdoQuery("UPDATE wi_indv_training 
            SET is_deleted=0,indv_source='Group' 
            WHERE trn_id='$trn_id' 
             AND ind_id='$ind_id'"); 
      } 
      else 
      { 
       $this->db->insert("wi_indv_training", 
            array("ind_id"=>$ind_id, 
             "indv_source"=>'Group', 
             "trn_id"=>$trn_id, 
             "attendance"=>"yes", 
             "active"=>"yes")); 
      }     
     } 
    } 
    else 
    { 
     $this->db->insert("wi_trn_org",array('trn_id'=>$trn_id,'grp_id'=>$value)); 
     $grp_indv=$this->db->pdoQuery("SELECT ind_id 
             FROM wi_indv_org 
             WHERE grp_id='$value' 
             AND is_deleted=0")->results(); 
       foreach ($grp_indv as $ke => $va) 
       { 
        $ind_id=$va['ind_id']; 
        $rows=$this->db->pdoQuery("SELECT * 
               FROM wi_indv_training 
               WHERE trn_id='$trn_id' 
               AND ind_id='$ind_id'")->results(); 
        if(count($rows)>0) 
        { 
         $this->db->pdoQuery("UPDATE wi_indv_training 
              SET is_deleted=0, 
               indv_source='Group' 
              WHERE trn_id='$trn_id' 
               AND ind_id='$ind_id'"); 
        } 
        else 
        { 
         $this->db->insert("wi_indv_training", 
              array("ind_id"=>$ind_id, 
               "indv_source"=>'Group', 
               "trn_id"=>$trn_id, 
               "attendance"=>"yes", 
               "active"=>"yes")); 
        }     
       } 
      } 
     } 

任何人都可以幫助關於性能增強的最佳算法?

回答

1

這裏的主要問題是你在一個循環中的多個查詢:

foreach ($grp_id as $key => $value) { 
      # code... 
      $rs=$this->db->pdoQuery("SELECT * FROM wi_trn_org WHERE trn_id='$trn_id' AND grp_id='$value'")->results();    
... 
} 

沒有爲每個SQL查詢的性能損失,因此,如果你的循環運行1000次,你打的性能瓶頸1001次。

解決此問題的方法是在循環內重新構造查詢,作爲循環外部查詢的一部分。第一個查詢可以重寫爲原始查詢的JOIN,這可能會給您足夠的性能來解決您的問題。如果這還不夠,你可以將所有這些折成Stored Routine

+0

能否請您詳細說明一下例子。我嘗試使用INSERT INTO ... ON DUPLICATE KEY UPDATE。但我無法得到結果。 – 2014-09-01 05:33:58

+0

你做了我建議的重試:試圖讓第一個SQL SELECT語句退出循環?那工作?這將比嘗試解決整個事情更簡單 - 取決於您的數據庫大小,這可能就足夠了。 – JasonS 2014-09-01 12:13:33

+0

這減少了Loop中多個SELECT查詢的開銷,從而減少了時滯。 – 2014-09-02 04:21:18

0

我研究並找到了解決我的查詢,即

 $this->db->pdoQuery("UPDATE wi_trn_org SET is_deleted=1 WHERE trn_id='$trn_id'"); 
     $this->db->pdoQuery("UPDATE wi_indv_training SET is_deleted=1 WHERE trn_id='$trn_id'"); 
     $this->db->pdoQuery("INSERT INTO wi_trn_org(trn_id, grp_id) SELECT $trn_id AS trn_id, grp_id FROM wi_group WHERE grp_id IN ($grp) AND grp_id NOT IN (SELECT DISTINCT (grp_id) FROM wi_trn_org)"); 
     $this->db->pdoQuery("UPDATE wi_trn_org SET is_deleted=0 WHERE trn_id='$trn_id' AND grp_id IN ($grp)"); 
     $this->db->pdoQuery("INSERT INTO wi_indv_training(ind_id, trn_id) SELECT ind_id, $trn_id AS trn_id FROM wi_indv_org WHERE grp_id IN ($grp) AND ind_id NOT IN (SELECT DISTINCT (ind_id) FROM wi_indv_training WHERE trn_id =$trn_id)"); 
     $this->db->pdoQuery("UPDATE wi_indv_training SET is_deleted=0,indv_source='Group',attendance='yes',active='yes' WHERE trn_id='$trn_id' AND ind_id IN (SELECT DISTINCT(ind_id) FROM wi_indv_org WHERE grp_id IN ($grp))"); 

這爲我提供了在一定程度上增強性能的解決方案。這個算法是否真的增強了查詢性能?

+0

讓我們來看看。你說你有一些表演。您發佈了一些查詢。根據你寫的內容,結果是你有表現。 Ergo是唯一可能的邏輯結論,即上面的代碼確實提高了性能。問題是,你是否瞭解幕後發生了什麼以及數據庫如何調整以實現性能? – 2014-09-01 15:04:41

+0

是的,我明白了背後發生了什麼。 – 2014-09-02 14:01:25