2014-09-30 71 views
1

執行我有一個創建基於一個巨大的數組的查詢功能PHP - MySQL的:如何讓一個巨大的插入查詢4個萬多行

public function importFromCSV($uploaded_file) { 
    set_time_limit(0); 

    $arr = Utils::csvToAarray($uploaded_file["tmp_name"]); 
    if(empty($arr)) { 
     return false; 
    } 
    //Base query 
    $query = "INSERT INTO ".$this->tablename." VALUES "; 

    //var_dump($arr); exit; //DEBUG 

    $i = 0; 
    $totalRows = count($arr); 
    foreach($arr as $row) { 
     $r = array_values($row); 
     //If title is not empty 
     if(!empty($r[1])) { 
      $query .= "("; 
      $query .= "null,"; //Enables Auto Increment 
      $query .= "'".$r[1]."',"; //Title 
      $query .= "'".$r[0]."',"; //Referemce 

      //Formats cost and price 
      $rawCost = $r[4]; 
      $cost = preg_replace('/\D/', '', $rawCost); 
      $rawPrice = $r[6]; 
      $price = preg_replace('/\D/', '', $rawPrice); 
      $rawStock = $r[2]; 
      $stock = (int)preg_replace('/\D/', '', $rawStock); 

      $query .= $cost.","; 
      $query .= $price.","; 
      $query .= "'".$r[3]."',"; 
      $query .= $stock; 
      $query .= ")"; 

      //Separates each insert with a coma but only if it's not the last one 
      if($i < $totalRows) { 
       $query .=","; 
      } 
     } else { 
      $totalRows--; //Removes the omitted row from the array count 
     } 
     $i++; 
    } 
    if($this->conn->query($query)) { 
     echo "QUERY FINISHED"; 
    } 
    exit; 
} 

現在正確生成查詢是巨大的。該數組包含近40,000行。

查詢生成正確。問題出現在函數的最後幾行。你看到我稱之爲方法查詢(來自PDO類)。如果查詢成功執行,則應回顯「QUERY FINISHED」,但不會。我試圖刪除時間執行時間限制,但它也不起作用。

如果生成的查詢有20,30,100個插入,它將正常工作並插入所有數據。

但是,當它有近40,000插入它不起作用。我不介意只要插入所有數據就會花費數分鐘時間。

我該如何做到這一點?

+2

創建一個臨時文件,並使用[LOAD DATA INFILE(http://dev.mysql.com/doc/refman/5.1/en/load-data.html) – 2014-09-30 23:59:19

+0

多少行它插入?另外,你有沒有檢查過你的Apache錯誤日誌? – 2014-10-01 00:01:07

+0

它不會插入任何內容。當我得到一個有幾十行插入的普通數組時,它們完全插入。但是當查詢有40,000個插入時,它不會插入它們中的任何一個。 ------順便說一下,我也在考慮使用LOAD DATA INFILE。創建一個新的Temp CSV而不是查詢。 – JuanBonnett 2014-10-01 00:06:09

回答

1

拆分爲1,000每個

public function importFromCSV($uploaded_file) { 
set_time_limit(0); 

$arr = Utils::csvToAarray($uploaded_file["tmp_name"]); 
if(empty($arr)) { 
    return false; 
} 
//var_dump($arr); exit; //DEBUG 

$i = 0; 
$ii = 0; 
$totalRows = count($arr); 
foreach($arr as $row) { 
    $r = array_values($row); 
    //If title is not empty 
    if(!empty($r[1])) { 
     // new: Base query starts here 
     if($ii == 0) $query = "INSERT INTO ".$this->tablename." VALUES "; 
     $ii++; 
     $query .= "("; 
     $query .= "null,"; //Enables Auto Increment 
     $query .= "'".$r[1]."',"; //Title 
     $query .= "'".$r[0]."',"; //Referemce 

     //Formats cost and price 
     $rawCost = $r[4]; 
     $cost = preg_replace('/\D/', '', $rawCost); 
     $rawPrice = $r[6]; 
     $price = preg_replace('/\D/', '', $rawPrice); 
     $rawStock = $r[2]; 
     $stock = (int)preg_replace('/\D/', '', $rawStock); 

     $query .= $cost.","; 
     $query .= $price.","; 
     $query .= "'".$r[3]."',"; 
     $query .= $stock; 
     $query .= ")"; 

     //Separates each insert with a coma but only if it's not the last one 
     if($i < $totalRows) { 
      $query .=","; 
     } 
     if($ii % 1000 == 0){ 
      $this->conn->query($query); // insert the 1000 that have been put into the string 
      $query = ""; //reset the string 
      $ii=0; //reset counter so query can be built again 
     } 
    } else { 
     $totalRows--; //Removes the omitted row from the array count 
    } 
    $i++; 
} 
if($this->conn->query($query)) { 
    echo "QUERY FINISHED"; 
} 
exit; 
} 

因爲PDO ::查詢是一個「同步」呼叫插入時,PHP必須等到第一個完成插入到移動到下一個插入。這會將所有數據從csv分析的行逐行放入數據庫,但一次只能放入1,000個。注意我沒有測試過這個,但這個概念顯然存在。

+0

好的。我試過這個,它工作。我做了一些細微的變化: 1)我把它分成128點的插入,而不是1000。2)我不得不在代碼中的變化,因此去除每個查詢的最後昏迷。 其餘。它工作完美。只需要幾秒鐘執行,所有的行都可以完美插入。 – JuanBonnett 2014-10-01 00:48:46