2011-06-01 76 views
0

我目前使用下面的代碼來獲取uuid的列表,然後將它們分成1000個組,然後將這些組插入到數據庫中。代碼點火器活動記錄 - 幫助精簡過程

這工作得很好,除了這個已經在時間上下工夫,超過一百萬的UUID的 的問題是這種使用的內存的巨量,所以我需要幫助簡化此過程中使用較少的內存...

public function send_daily_email($dealId) { 
    set_time_limit(0); 
    $deal = $this->ci->deal->get($dealId); 
    if ($deal == false) 
    throw new exception('Unknown Deal Specified'); 

    $users = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->get(); 

    if ($users->num_rows() == 0) 
    throw new exception('No users in region'); 

    $message = $this->ci->load->view('emails/daily', array('name' => $deal->title, 'content' => $deal->snippet), true); 
    $uuids = array(); 

    foreach ($users->result() as $u) 
    $uuids[] = $u->uuid; 

    $uuids = array_chunk($uuids, 1000); 

    $sendId = 0; 
    foreach ($uuids as $batch) { 
    $count = count($batch); 
    $this->db->set('dealId', $dealId)->set('content', $message)->set('regionId', $deal->region)->set('recipients', $count)->set('created', 'NOW()', false)->set('status', 'Creating'); 
    if ($sendId === 0) { 
     $this->db->insert('dealEmailParent'); 
     $sendId = $this->db->insert_id(); 
     $this->db->set('sendId', $sendId)->where('id', $sendId)->update('dealEmailParent'); 
    } 
    else 
     $this->db->set('sendId', $sendId)->insert('dealEmailParent'); 

    $insert = array(); 

    foreach ($batch as $uuid) 
     $insert[] = array('parentId' => $sendId, 'uuid' => $uuid); 

    $this->db->insert_batch('dealEmailChild', $insert); 
    } 
} 

回答

0

這返工可以插入1,000,000「用戶」一分鐘之內沒有任何的內存限制:)

public function create_daily_email($dealId) 
    { 
     $time_start = microtime(true); 
     set_time_limit(0); 
     $deal = $this->ci->deal->get($dealId); 
     if ($deal == false) 
      throw new exception('Unknown Deal Specified'); 


     $message = $this->ci->load->view('emails/daily', array('name' => $deal->title, 'content' => $deal->snippet), true); 

     $start = 0; 
     $end = 50000; 

     $q = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->limit($end, $start)->get(); 
     $sendId = 0; 

     while ($q->num_rows() != 0) { 

      //do stuff 

      $uuids = array(); 

      foreach ($q->result() as $u) 
       $uuids[] = $u->uuid; 

      $uuids = array_chunk($uuids, 1000); 

      foreach ($uuids as $batch) { 
       $count = count($batch); 
       $this->db->set('dealId', $dealId)->set('content', $message)->set('regionId', $deal->region)->set('recipients', $count)->set('created', 'NOW()', false)->set('status', 'Creating'); 
       if ($sendId === 0) { 
        $this->db->insert('dealEmailParent'); 
        $sendId = $this->db->insert_id(); 
        $this->db->set('sendId', $sendId)->where('id', $sendId)->update('dealEmailParent'); 
        $parentId = $sendId; 
       } 
       else { 
        $this->db->set('sendId', $sendId)->insert('dealEmailParent'); 
        $parentId = $this->db->insert_id(); 
       } 

       $insert = array(); 

       foreach ($batch as $uuid) { 
        $insert[] = array(
         'parentId' => $parentId, 
         'uuid' => $uuid 
        ); 
       } 

       $this->db->insert_batch('dealEmailChild', $insert); 
      } 

      //stop stuff 

      unset($q); 
      unset($uuids); 
      unset($insert); 
      $start = $start + $end; 
      $q = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->limit($end, $start)->get(); 
     } 

     $this->db->set('status', 'Pending')->where('sendId', $sendId)->update('dealEmailParent'); 

     $time_end = microtime(true); 
     $time = $time_end - $time_start; 

     die("Did nothing in $time seconds"); 
    } 
0

我討厭這麼說,但是從我對CodeIgniter的瞭解中,知道獲取結果的唯一方法是一次獲取整個結果集,即使您只需要一行,或者即使您想要一次取一行並做一些處理。它不像本機mysql(i)/ PDO功能那樣使用遊標進行操作。

對於這個龐大的數據集,我建議堅持原生的PHP數據庫函數和前面的CodeIgniter的活動記錄數據庫類。

+0

我應該說,它不具備的功能,以獲取一個單行,但主要結果和result_array功能每次生成整個結果集。 – 2011-06-01 02:58:40