用户
 找回密码
 入住 CI 中国社区
搜索
查看: 3035|回复: 7
收起左侧

10个百万级数据表需经过程序处理后整理导入到新表中

[复制链接]
发表于 2012-8-11 10:25:47 | 显示全部楼层 |阅读模式
CI刚入手几天新人初发帖,求助老鸟们

手上有个案子涉及到千万级(分十一个表,每个近百万)的数据量,数据全部从EXCEL手工导出到MYSQL花了好几天时间

现在需要通过WEB的方式查询编辑用到数据

因为数据不规范有重复记录,所以现在初用CI2.1.1在整个导入代码来导

目前的方式是这样

一次性读取100条记录存入对象

循环对其进行处理并存入临时数组

然后将数组数据存入新的表内,循环一次存入一次 (原先的想法是循环100条记录后处理过的数据存一数组,再把存入数组的数据一次插入到新表内,以减少数据库操作,因PHP也是现学现卖所以没有实现成功)

因为会有重复记录100条记录,平均实际进行插入操作40次

然后返回视图,停顿一秒JS自动跳转执行下一次导入操作

现在以这种方式导入数据,

执行程序跳转时,浏览器进度条没有像打开新页面那样跳转一次刷新一次,另外处理到30000条记录的时候,网页就停止影响.

望高人指点迷津~~

代码回帖附上
 楼主| 发表于 2012-8-11 10:31:06 | 显示全部楼层
模型

PHP复制代码
 
 <?php
class Madmin extends CI_Model {
 function __construct()
    {
        parent::__construct();
  $this->load->database();
 
 }
 
 function get_customer_record($ic_number,$cur_record)//根据字段ic_number查询一条记录
 {
  $this->db->select('ic_number,mobile_phone,other_phone');
  $this->db->where('ic_number',$ic_number);
  if ($cur_record > 100)
  {
   $query = $this->db->get('customer',5,$cur_record-5);//重复的记录都相近
  }else{
   $query = $this->db->get('customer');
  }
  return $query->row();
 }
 function get_customer_list_page($db_name,$offset,$limit)//自定读取某数据表N条记录
 {
  $query = $this->db->get($db_name,$limit,$offset);
  return $query->result();
 }
 
 function insert_db($data)//处理过的数据通过数组插入到指定的表
 {
  $this->db->insert('customer',$data))
 }
 function update_db($ic_number,$phone_type,$phone)//根据条件更新mobile_phone,other_phone字段数据
 {
  if ($phone_type == 'mobile')
  {
   $this->db->set('mobile_phone',$phone);
  }else{
   $this->db->set('other_phone',$phone);
  }
  $this->db->where('ic_number',$ic_number);
  $this->db->update('customer');
 }
}
?>
 
复制代码


控制器:
PHP复制代码
 
 <?php
class Admin extends CI_Controller {
 var $base_url;
 function __construct()
 {
  parent::__construct();
  $this->load->helper('url');
  $this->base_url = $this->config->item('base_url');
  $this->load->library('pagination');
 }
  //将客户数据从各零散数据表,通过清除重复记录,判断同信息不同电话号码信息
 //重新整理后导入custmoer表内
 function customer_import()//导入整理客户数据
 {
  $data['baseurl'] = $this->base_url;
  $source = 'maybank_0';
  $cur_record = $this->uri->segment(3);
  if (empty($cur_record)){$cur_record = 0;}
  $limit = 10;
  $data['cur_record'] = $cur_record + $limit;
  $data['limit'] = $limit;
  $this->load->model('Madmin');
  if ($source <> Null)
  {
   $temp_data = array();
   $data['import_data'] = $this->Madmin->get_customer_list_page($source,$cur_record,$limit);
   foreach ($data['import_data'] as $row)
   {
    ++$cur_record;
    if (substr($row->phone,0,1) == '1' or substr($row->phone,0,2) == '01' or substr($row->phone,0,3) == '001' or substr($row->phone,0,3) == '601')
    //检测电话号为手机的号码
    {
     $temp_data['mobile_phone'] = $row->phone;
     $phone_type = 'mobile';
    }else{
     $temp_data['other_phone'] = $row->phone;  
     $phone_type = 'other';
    }
    $result = $this->Madmin->get_customer_record($row->ic_number,$cur_record);
    if (!empty($result))
    {
     if ($result->ic_number == $row->ic_number)
     //根据身份证号(ic_number)判断是否有重复记录和电话号码类型,忽悠重复记录及更新或追加电话号码信息
     {
      $phone = '';
      if ($phone_type == 'mobile' and $result->mobile_phone <> NULL)
      {
       $phone = $result->mobile_phone.','.$row->phone;
      }else if ($phone_type == 'other' and $result->other_phone <> NULL){
       $phone = $result->other_phone.','.$row->phone;
      }else{
       $phone = $row->phone;
      }
      $this->Madmin->update_db($row->ic_number,$phone_type,$phone);
      unset($temp_data);
      continue;
     }
    }
   
    $temp_data['name'] = $row->name;
    $temp_data['category_id'] = 1;
    $temp_data['ic_number'] = $row->ic_number;
    $temp_data['address_1'] = $row->address_1;
    $temp_data['address_2'] = $row->address_2;
    $temp_data['address_3'] = $row->address_3;
    $temp_data['address_4'] = $row->address_4;
    $temp_data['postcode'] = $row->postcode;
    $temp_data['sex'] = $row->sex;
    $temp_data['name'] = $row->name;
    $temp_data['race_cd'] = $row->race_cd;
    $temp_data['credit_limit'] = 0;
    $this->Madmin->insert_db($temp_data);
    unset($temp_data);
   }
   $data['success'] = '共执行处理&nbsp;'.$data['cur_record'].'&nbsp;条记录!['.date("H:i:s").']</br>';
  }
  $this->load->view('customer_import',$data);
 }
}
 
 
复制代码


视图:
HTML复制代码
 
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<base href="<?=$baseurl?>">
<title>数据导入处理</title>
</head>
<body>
<?=$success?>
<?
if ((844610-$cur_record) > $limit)
{
 $url = site_url("admin/customer_import/$cur_record");
 echo('<script>');
 echo("setTimeout(location.href='$url',2000);");
 echo('</script>');
 
}else{
 echo('数据全部导入成功!');
}?>
</body>
</html>
 
 
复制代码

 楼主| 发表于 2012-8-11 17:43:33 | 显示全部楼层
大哥们今天都休息哦!!??
 楼主| 发表于 2012-8-15 16:14:38 | 显示全部楼层
自己顶一顶..

我问的问题太初级了吗 还是太高级拉 
 楼主| 发表于 2012-9-4 21:27:13 | 显示全部楼层
再顶一顶。。
发表于 2012-9-5 11:19:13 | 显示全部楼层
1、如果你这个是一次性的导入工作,建议用个脚本或写个应用程序来做,更合适
2、千万级别的数据量,数据库和应用可能需要做一些优化工作,否则效率可能会低,想无脑高效查询的话可以考虑一下Nosql数据库
 楼主| 发表于 2012-9-6 17:31:43 | 显示全部楼层
谢谢楼上的。。


现在这样写算是分段导入吧。。DZ的论坛有用过吗?后台备份数据库时类似的功能,计划是那样

不知道算不算真正的分段导入,不会一下卡死MYSQL
 楼主| 发表于 2012-11-9 11:11:48 | 显示全部楼层
路过顶一顶。

经过一段时间其他事务的处理,又回到要处理这个事情上面

本版积分规则