2015-08-16 32 views
0

我見過多個線程討論這個問題,但答案總是存在完全不同的結論。特別是我想知道是否真的有必要創建一個自己準備好的語句(使用適當數量的佔位符),以便將其作爲單個查詢插入。 我預計,當我在我的for循環之前和之後使用beginTransactionendTransaction時,pdo/php會等待事務處理,直到收集完所有數據爲止,並且一旦服務器命中endTransaction,就會將這些數據作爲單個查詢發送。多行插入儘可能快

爲了達到最佳性能(它通常在1到300行之間,但也可能達到2000行),我需要如何重寫這樣一個for循環插入多個插入。

for($i=0; $i<$baseCount; $i++) 
    { 
     $thLevel = $bases[$i]["ThLevel"]; 
     $gold = $bases[$i]["Gold"]; 
     $elixir = $bases[$i]["Elixir"]; 
     $darkElixir = $bases[$i]["DarkElixir"]; 
     $dateFound = $elixir = $bases[$i]["TimeFound"]; 

     $query = $db->prepare("INSERT INTO bot_attacks_searchresults (attack_id, available_gold, available_elixir, available_dark_elixir, date_found, opponent_townhall_level) 
     VALUES (:attack_id, :available_gold, :available_elixir, :available_dark_elixir, :date_found, :opponent_townhall_level)"); 
     $query->bindValue(':attack_id', $attackId); 
     $query->bindValue(':available_gold', $gold); 
     $query->bindValue(':available_elixir', $elixir); 
     $query->bindValue(':available_dark_elixir', $darkElixir); 
     $query->bindValue(':date_found', $dateFound); 
     $query->bindValue(':opponent_townhall_level', $thLevel); 
     $query->execute(); 
    } 
+0

有多快,我們談論的 – Rohit

+0

構建循環內的查詢。在循環外執行查詢。 – Strawberry

回答

0

這裏是概念的一個非常粗略的證明:

<?php 

$values = array(); 

for($i=0;$i<10;$i++) 
{ 
$values[] = "($i)"; 
} 

$values = implode($values,','); 

$query = "INSERT INTO my_table VALUES $values"; 

echo $query; 

?> 

輸出INSERT INTO my_table VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)

您將需要略微重組這與準備(PHP是不是我的專長)工作,但原則是一樣的;即您在循環內部構建查詢,但只執行一次。

1
  • 準備語句一次。 MySQL將它解凍一次,因此任何後續對查詢的調用都會很快,因爲它已經是lexed並且需要參數。

  • 在循環之前啓動事務。這樣做是爲了讓您的硬盤驅動器可以在一個輸入輸出操作中寫下所有行。默認模式是1插入query = 1的hdd的I/O。

  • 創建循環,綁定你的參數存在並調用$query->execute();

  • 退出循環,commit()交易。

全碼:

$db->beginTransaction(); 

$query = $db->prepare("INSERT INTO bot_attacks_searchresults (attack_id, available_gold, available_elixir, available_dark_elixir, date_found, opponent_townhall_level) 
     VALUES (:attack_id, :available_gold, :available_elixir, :available_dark_elixir, :date_found, :opponent_townhall_level)"); 

for($i = 0; $i < $baseCount; $i++) 
{ 
    $thLevel = $bases[$i]["ThLevel"]; 
    $gold = $bases[$i]["Gold"]; 
    $elixir = $bases[$i]["Elixir"]; 
    $darkElixir = $bases[$i]["DarkElixir"]; 
    $dateFound = $elixir = $bases[$i]["TimeFound"]; 

    $query->bindValue(':attack_id', $attackId); 
    $query->bindValue(':available_gold', $gold); 
    $query->bindValue(':available_elixir', $elixir); 
    $query->bindValue(':available_dark_elixir', $darkElixir); 
    $query->bindValue(':date_found', $dateFound); 
    $query->bindValue(':opponent_townhall_level', $thLevel); 
    $query->execute(); 
} 

$db->commit(); 
+0

這樣的事情就是我所期望的。我已經讀過一次,我需要InnoDB作爲MySQL中的表引擎,這是真的嗎?我要試一試 – kentor

+0

正確,你需要符合ACID標準的引擎。 InnoDB或TokuDB。 –