2012-08-23 69 views
1

該方法用於選擇User和TargetUser之間的動作數量,例如,就在兩個用戶之間。該方法的結果值取決於GetTotalOfPossibleActions()返回值,該值是動態的(每個用戶都有自己的編號)。將值計算移至SQL層的PHP層是否更好?

問題:將值計算移動到SQL層以外的SQL更好嗎?

public function GetAction() { 

    // ... 

    $MaxActionCount = $this->GetTotalOfPossibleActions(); 

    return registry::getInstance()->get('DB')->select(
     'SELECT 
      `Action` 
      , `HA`.`Id` AS `ActionId` 
      , IF(`Count` IS NULL 
       , IF('.$MaxActionCount.' % 2 
        , IF(`HA`.`Id` = 1 
         , CEIL('.$MaxActionCount.'/2) 
         , FLOOR('.$MaxActionCount.'/2)) 
        , '.$MaxActionCount.'/2) 
       , GREATEST(IF('.$MaxActionCount.' % 2 
        , IF(`HA`.`Id` = 1 
         , CEIL('.$MaxActionCount.'/2) - CONVERT(`H`.`Count`, SIGNED) 
         , FLOOR('.$MaxActionCount.'/2) - CONVERT(`H`.`Count`, SIGNED)) 
        , '.$MaxActionCount.'/2 - `H`.`Count`), 0) 
      ) AS `CountLeft` 
     FROM `Help` AS `H` 
     RIGHT JOIN `HelpAction` AS `HA` 
     ON `H`.`ActionId` = `HA`.`Id` 
     AND `UserId` = '.$this->UserId.' 
     AND `TargetUserId` = '.$this->TargetUserId.' 
     AND `CreatedDate` = CURDATE()')); 

} 
+3

的方式你只是砰變量到SQL重新評估是非常令人擔憂的。至少應該使用佔位符來避免SQL注入漏洞或更糟的情況。 – tadman

+0

由於$ MaxActionCount是內部值,SQL注入在這裏是不可能的。 –

+4

@羅曼這甚至不是重點。如果您不使用參數化查詢,則數據庫引擎無法重新使用您的查詢。每次你用它打到數據庫時,它都必須被完全解析。將其轉換爲存儲過程並將值作爲參數發送。與從這裏到那裏轉移一些簡單的數學運算相比,這將節省更多的時間。 – Tomalak

回答

2

沒有硬性的答案,但以下是我申請的一般指南。

PHP服務器可以進行負載平衡和相乘。所以如果你的CPU週期不足,你可以相對容易地添加另一個PHP服務器。相反,MySQL服務器不容易相乘。您可以添加複製服務器並在從屬服務器上運行復雜的「選擇」,但複製會增加一點壓力,並且主服務器上的更新與從服務器上的更新之間總會有延遲。 (絕對不要相信數據庫管理員說這是毫秒;而當服務器處於壓力/備份等情況下它會變慢)

因此,PHP +1。

但是,SQL的構建和設計使用數據進行計算。這是工作。它更有效率(假設你正確設計表,查詢和索引)。

所以+1給mySQL。

如果您在MySQL上進行計算,您也不需要將整個數據表傳輸到PHP進行處理和處理。這節省了兩者之間的網絡流量。

所以+1給mySQL。

但是,如果您正在努力獲得正確的查詢,或者MySQL正在使用所有內存,不停地創建臨時表並交換到硬盤,那麼通過細分來調試和查找問題會容易得多在PHP中進行計算。 MySQL EXPLAIN和緩慢的查詢日誌有時會令人沮喪。

所以+1給PHP。

所以... 2個所有。如果你在一臺服務器上同時使用這兩種查詢,並且查詢不會給你帶來麻煩,那麼讓MySQL來做這件事吧。如果您在查詢時遇到問題,請回到PHP。如果你在多臺服務器上,儘可能在MySQL中儘可能多地做,而不會遇到瓶頸。如果MySQL是瓶頸和複製不可能,請回到PHP。但是,然後檢查網絡流量。

那麼請記住,當你負荷增加...

+0

PHP服務器在AWS Auto Scaling下,DB是主/從+副服務器。我現在把它移到SP,讓我們看看... –