2013-10-17 49 views
0

我有一個foreach循環遍歷數組。內存/高效數據庫條目

在每個實例中,我將數組組織到一個查詢字符串中,並使用MySQLi將它添加到數據庫中。

function storeProperties($data, $db) { 
    foreach ($data['property'] as $property) { 
     $query_string = "INSERT INTO table VALUES(..., ..., ...,)" 
     $db->query($query_string); 
     echo $db->error; 
    } 
} 

有沒有更好的方法我應該這樣做?
顯然,這種方法使用n數據庫查詢一個接一個,所以這是內存密集型和時間密集型的。

有沒有更好的方法來做到這一點? 我應該將每個查詢連接成單個字符串並在for循環之外運行嗎?

+0

請注意,PHP CONCAT也使用內存和CPU,因爲你需要計算,如果CONCAT查詢的最大數據包大小包內適合關閉服務器(defualt 1MB)關於MySQL的設置。 –

+0

是的。在循環內部構建整個查詢字符串(「INSERT INTO table VALUES」除外),然後在循環完成後執行它。那樣,數據庫只有一次往返。 – Strawberry

回答

0

以下方法來自我的PDO主力,用於批量插入。它創建一個包含多個VALUES條目的單個INSERT語句。

使用它作爲

$db->bulkinsert(
    'tbl_my_tablename', 
    array('fieldname_1','fieldname_2', 'fieldname_3'), 
    array(
     /* rec1 */ array('r1f1', 'r1f2', 'r1f3'), 
     /* rec2 */ array('r2f1', 'r2f2', 'r2f3'), 
     /* rec3 */ array('r3f1', 'r3f2', 'r3f3') 
    )); 

請注意,該方法是由一個複雜的類定義的剪斷,這裏使用了一些方法不是在代碼片段包含,特別是$this->connect()(連接到PDO),$this->begin()(開始交易),$this->commit()$this->rollback(),靜態Log類記錄類似Apache的百科全書;-)

但我敢肯定這是你可能需要的東西。

/** 
    * Performs fast bulk insertion 
    * Parameters: 
    *  $tablename 
    *  $datafields - non-assiciative array of fieldnames 
    *     or propertynames if $data is an array of objects 
    *  $data  - array of either non-associative arrays (in the correct order) 
    *     or array of objects with property names matching the $datafields array 
    */ 
    const MAX_BULK_DATA = 3000; 
    public function bulkinsert($tablename, $datafields, &$data) { 
     $result = 0; 
     try { 
      try { 
       $this->connect(); 
       $datacount = count($data); 
       // loop until all data has been processed 
       $start = 0; 
       $lastbinds = 0; 
       $this->begin(); 
       while ($start < $datacount) { 
        $ins = array(); 
        $bindscount = min(self::MAX_BULK_DATA, $datacount - $start); 
        if ($bindscount != $lastbinds) { 
         // prepare the binds 
         $binds = substr(str_repeat(',?', count($datafields)), 1); 
         $binds = substr(str_repeat(",($binds)", $bindscount), 1); 
         $lastbinds = $bindscount; 
        } 
        for ($go = $start, $last = $start + $bindscount; $go < $last; $go++) { 
         if (is_object($data[$go])) { 
          try { 
           foreach($datafields as $propname) { 
            $rfl = new ReflectionProperty($data[$go], $propname); 
            $rfl->setAccessible(true); 
            $ins[] = $rfl->getValue($data[$go]); 
           } 
          } 
          catch(ReflectionException $e) { 
           throw new InvalidArgumentException('PDOCONNECT_ERR_SQL_UNKNOWN_PROPERTY', 0, $e); 
          } 
         } 
         else { 
          foreach($data[$go] as $value) { 
           $ins[] = $value; 
          } 
         } 
        } 
        $sql = sprintf('INSERT INTO %s (%s) VALUES %s', $tablename, join(',',$datafields), $binds); 
        Log::trace($sql); 
        $stmt = $this->pdo->prepare($sql); 
        $stmt->execute($ins); 
        $start = $last; 
        $result += $bindscount; 
       } 
       $this->commit(); 
      } 
      catch(PDOException $e) { 
       // do something with the exception if necessary 
       throw $e; 
      } 
     } 
     catch(Exception $e) { 
      $this->rollback(); 
      throw $e; 
     } 
     return $result; 
    } 
}