2013-08-02 54 views
6

私はinsert_batch()を使用して、10000以上の行をデータベースのテーブルに大量に挿入しています。私はいくつかのテストをしていますが、時には10.000以上の行が正しく挿入されていることに気がつきましたが、いくつかのケースではテーブルの総数が100以上の行が欠けています。何千もの挿入があるCodeigniterのinsert_batch()にレコードがありません

私が持っているレコードのフィールドデータは、私のテストごとに同じデータを使用しているので大丈夫ですが、ほとんど問題はありません。たとえば、私は20回、同じデータをデータベースに挿入しようとしました.19回になるとすべての行が正しく挿入されますが、この1回では100または多分もっと多くの行が欠けてしまいます。 insert_batch()ため

機能は次のとおりです。

protected function save_sms_to_database() { 
    //insert_Batch 
    $datestring = "%Y-%m-%d %h:%m:%s"; 
    $time = time(); 
    $datetime = mdate($datestring, $time); 

    $this->date_sent = $datetime; 

    foreach ($this->destinations as $k => $v) { 
     $sms_data[$k] = array(
      'campaign_id' => $this->campaign_id, 
      'sender_id' => $this->from, 
      'destination' => $v, 
      'token' => md5(time() . 'smstoken' . rand(1, 99999999999)), 
      'message' => $this->body, 
      'unicode' => $this->unicode, 
      'long' => $this->longsms, 
      'credit_cost' => $this->eachMsgCreditCost, 
      'date_sent' => $this->date_sent, 
      'deleted' => 0, 
      'status' => 1, 
      'scheduled' => $this->scheduled, 
     ); 
    } 

    $this->ci->db->insert_batch('outgoingSMS', $sms_data); 
    if ($this->ci->db->affected_rows() > 0) { 
     // outgoingSMS data were successfully inserted  
     return TRUE; 
    } else { 
     log_message('error', $this->campaign_id.' :: Could not insert sms into database'); 
     log_message('error', $this->ci->db->_error_message()); 
     return FALSE; // sms was not inserted correctly 
    } 
} 

私は、このような機会のためinsert_batch()をデバッグするにはどうすればよいですか?

DB_active_rec.phpにいくつかの変更を加えて、insert_batch中にいくつかのロギングを行いましたが、これまでに何がうまくいかないかを確認するために問題を再現できませんでした。しかし、問題が最初に2〜3回出現し、それを修正するロジックが大幅に変更されていない限り、私はcodeigniterのinsert_batch()機能を信頼できないので、このままにすることはできません。

また、私はCodeIgniterのinsert_batch()関数を追加している:

public function insert_batch($table = '', $set = NULL) 
{ 
     $countz = 0; 
    if (! is_null($set)) 
    { 
     $this->set_insert_batch($set); 
    } 

    if (count($this->ar_set) == 0) 
    { 
     if ($this->db_debug) 
     { 
      //No valid data array. Folds in cases where keys and values did not match up 
      return $this->display_error('db_must_use_set'); 
     } 
     return FALSE; 
    } 

    if ($table == '') 
    { 
     if (! isset($this->ar_from[0])) 
     { 
      if ($this->db_debug) 
      { 
       return $this->display_error('db_must_set_table'); 
      } 
      return FALSE; 
     } 

     $table = $this->ar_from[0]; 
    } 

    // Batch this baby 
    for ($i = 0, $total = count($this->ar_set); $i < $total; $i = $i + 100) 
    { 

     $sql = $this->_insert_batch($this->_protect_identifiers($table, TRUE, NULL, FALSE), $this->ar_keys, array_slice($this->ar_set, $i, 100)); 

     //echo $sql; 

     $this->query($sql); 
        $countz = $countz + $this->affected_rows(); 
    } 

    $this->_reset_write(); 
      log_message('info', "Total inserts from batch:".$countz); 

    return TRUE; 
} 

私が予想よりも少ない挿入を持っているとき、私は非予測数を取得するようバッチからの総インサートを持つ最後のlog_message()も問題を示していますそこにもインサートがあります。

私のデータベースには何千もの行を挿入するために何か考えなければなりません。

誰かがこの種の問題の手掛かりを持っていますか?パフォーマンスの不足の間に、ハードドライブやシステムのメモリと関係するかもしれません。これは1GBのラムを搭載した古いPCです。

EDIT:要求されたとして、私が完了し、挿入したCodeIgniterのinsert_batch()機能

INSERT INTO `outgoingSMS` (`campaign_id`, `credit_cost`, `date_sent`, `deleted`, `destination`, `long`, `message`, `scheduled`, `sender_id`, `status`, `token`, `unicode`) VALUES ('279',1,'2013-08-02 02:08:34',0,'14141415151515',0,'fd',0,'sotos',1,'4d270f6cc2fb32fb47f81e8e15412a36',0), ('279',1,'2013-08-02 02:08:34',0,'30697000000140',0,'fd',0,'sotos',1,'9d5a0572f5bb2807e33571c3cbf8bd09',0), ('279',1,'2013-08-02 02:08:34',0,'30697000000142',0,'fd',0,'sotos',1,'ab99174d88f7d19850fde010a1518854',0), ('279',1,'2013-08-02 02:08:34',0,'30697000000147',0,'fd',0,'sotos',1,'95c48b96397b21ddbe17ad8ed026221e',0), ('279',1,'2013-08-02 02:08:34',0,'306972233469',0,'fd',0,'sotos',1,'6c55bc3181be50d8a99f0ddba1e783bf',0), ('279',1,'2013-08-02 02:08:34',0,'306972233470',0,'fd',0,'sotos',1,'d9cae1cbe7eaecb9c0726dce5f872e1c',0), ('279',1,'2013-08-02 02:08:34',0,'306972233474',0,'fd',0,'sotos',1,'579c34fa7778ac2e329afe894339a43d',0), ('279',1,'2013-08-02 02:08:34',0,'306972233475',0,'fd',0,'sotos',1,'77d68c23422bb11558cf6fa9718b73d2',0), ('279',1,'2013-08-02 02:08:34',0,'30697444333',0,'fd',0,'sotos',1,'a7fd63b8b053b04bc9f83dcd4cf1df55',0) 

によって生産されている9つの行で、ここでの例のINSERT文を入れています。

+0

この場合、単一のクエリ '(insert_batch)'の代わりにループにレコードを挿入することをお勧めします。このようにして、クエリをデバッグすることもできます。 –

+0

実行されているSQLクエリを表示できますか?おそらくいくつかは不正な形式ですか?大量のINSERTステートメントの使用を検討しましたか? – Halcyon

+0

@NiloySaha私は、私のシステムの性能を落とすので、このような大量の挿入には本当にループを使用できません。特に生産ではこれは悲惨です。私がインサートのために開発している間にループを使用したとき、私は覚えていても問題はありませんでしたが、このような膨大な量のインサートにこのロジックを使用することはできません。 – sotoz

答えて

3

insert_batch()は、MySQLが一度に処理するように設定されているデータよりも大きなデータを挿入しようとしています。 MySQLのオプションがmax_allowed_packetか何か他のものかどうかはわかりませんが、問題はバイト数と行数ではなく、制限を設定していることです。

DB_active_rec.php、mysql_driver.phpなどを編集する場合は、for()ループで100カウントを変更してみてください。 50がより安全な選択肢になるはずです。 で100行以上を挿入している場合、FYI-affected_rows()は正しい値を返しません。したがって、成功/エラーチェックとして使用することは信頼できません。 insert_batch()は一度に100レコードずつデータを挿入するのに対し、affected_rows()は最後のクエリのデータのみを返すためです。

+0

私は 'DB_active_rec.php'に行った変更を見ると、' affected_rows() 'の回答に感謝します。insert_batchで何個の挿入が行われたのかを正確に数えて、 (私は 'select count(*)'でそれを検証することもできます)。私はあなたが言ったようにループカウントを変更しようとし、そこでいくつかのテストを行います。すべてがうまくいくなら私はあなたの答えを受け入れるでしょう:) – sotoz

+0

あなたはこの問題をどのように乗り越えましたか教えてください。 – siva

0

この問題の解決策は、あなたがあなたの要件のサイズを設定することができ、ディレクトリ/system/database/と、開いているファイルDB_query_builder.phpに行くと

public function insert_batch($table, $set = NULL, $escape = NULL, $batch_size = 1000)

を更新する必要があり、です。

関連する問題