preloader
軟體工程

php stmt 的 bind_param 在大量連續向資料庫操作可以只做一次, 以加速執行時間

有時因為營運上的需求,會需要在資料庫先行大量新增、更新或刪除某些資料,在迴圈外寫下 bind_param(),而不是在迴圈內每個執行回合裡寫下 bind_param(),可以節省執行時間。以 PHP 語言和 T-SQL 語句在 MySQL 新增資料為例:


$sql = "INSERT INTO your_table_name (`column1`, `column2`, `column3`, `column4`, `column5`) VALUES (?, ?, ?, ?, ?) ";

$stmt = $mysqli->prepare($sql);

$stmt->bind_param("ssiii", $var1, $var2, $var3, $var4, $var5);

$var1 = "aa";

$var2 = "bb";

for($i = 0; $i < 1000; $i++ ){

// 假設迴圈執行一千次

  $var3 = $i;

  $var4 = $i + 1;

  $var5 = $i + 2;

  $stmt->execute();

}



$stmt->close();

 

如果搭配 begin_transaction() 和 commit(),效果會更明顯。原因是節省跟資料庫互動次數,先一次準備好所有要輸入的資料,最後再一次送出。


$sql = "INSERT INTO your_table_name (`column1`, `column2`, `column3`, `column4`, `column5`) VALUES (?, ?, ?, ?, ?) ";

$stmt = $mysqli->prepare($sql);

$stmt->bind_param("ssiii", $var1, $var2, $var3, $var4, $var5);

$var1 = "aa";

$var2 = "bb";

if ($mysqli->begin_transaction(`MYSQLI_TRANS_START_READ_WRITE`)) {

  for($i = 0; $i < 1000; $i++ ){
     // 假設迴圈執行一千次

     $var3 = $i;
     $var4 = $i + 1;
     $var5 = $i + 2;
     $stmt->execute();
   }

  // 到這邊已經完成一千次的迴圈執行

  if( !($mysqli->commit()) ) { // 這個條件內的$mysqli->commit()就會真正且一次送出到資料庫內

     // 如果$mysqli->commit() 失敗, 則取消先前的操作並回復上次狀態,以及印出資訊
     $mysqli->rollback();
     echo "大量新增資料時失敗, 本次對資料庫的操作將回復原狀.\n";

  } else {

     $stmt->close();
     echo "本次已完成大量新增資料, 將結束執行\n";
  }

}