處理大量資料匯入時,逐筆 INSERT 會造成嚴重效能瓶頸。本文展示 CodeIgniter 結合資料庫事務與分批提交的最佳實務,將寫入速度提升數倍。
insert_batch()trans_complete() 並重新開啟事務,避免長事務鎖定資源$sub_form = [];
$loop = 0;
$ins_loop = 0;
$sum = count($form_datas);
$this->logger->info('insert data total: ' . $sum);
$callStartTime = microtime(true);
$this->db->trans_start();
foreach ($form_datas as $item) {
$loop++;
$sub_form[] = $item;
// 每 200 筆或最後一筆執行批次插入
if (($loop % 200) == 0 || $loop == $sum) {
$this->logger->info('insert data num: ' . $loop);
$res = $this->kb_object_instance_mdl->insert_batch($sub_form, $obj_id);
$ins_loop++;
unset($sub_form); // 釋放記憶體
// 每 5 批次提交一次事務
if (($ins_loop % 5) == 0) {
$this->logger->info('insert data trans_complete ins_loop: ' . $ins_loop);
$this->db->trans_complete();
if ($loop != $sum) {
$this->db->trans_start(); // 重新開啟事務
}
}
}
}
$callEndTime = microtime(true);
$callTime = $callEndTime - $callStartTime;
$this->logger->info('insert data use time: ' . sprintf('%.4f', $callTime));
if ($this->db->trans_status() === TRUE) {
$this->_show_msg('1', ['data' => 'import ok']);
} else {
$this->_show_error('saveOrUpdate error');
}
| 參數 | 建議值 | 說明 |
|---|---|---|
| 單批筆數 | 200~500 | 視欄位數與 row size 調整,避免超過 max_allowed_packet |
| 事務提交頻率 | 每 5~10 批 | 平衡效能與資料一致性風險 |
| 記憶體管理 | unset 釋放 | 大量資料時防止 PHP 記憶體耗盡 |