lihuan34 发表于 2012-8-11 10:25:47

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

CI刚入手几天新人初发帖,求助老鸟们

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

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

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

目前的方式是这样

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

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

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

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

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

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

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

望高人指点迷津~~

代码回帖附上

lihuan34 发表于 2012-8-11 10:31:06

模型


<?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
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);
}
}



视图:

<!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>


lihuan34 发表于 2012-8-11 17:43:33

大哥们今天都休息哦!!??

lihuan34 发表于 2012-8-15 16:14:38

自己顶一顶..

我问的问题太初级了吗 还是太高级拉 :(

lihuan34 发表于 2012-9-4 21:27:13

再顶一顶。。

runer 发表于 2012-9-5 11:19:13

1、如果你这个是一次性的导入工作,建议用个脚本或写个应用程序来做,更合适
2、千万级别的数据量,数据库和应用可能需要做一些优化工作,否则效率可能会低,想无脑高效查询的话可以考虑一下Nosql数据库

lihuan34 发表于 2012-9-6 17:31:43

谢谢楼上的。。


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

不知道算不算真正的分段导入,不会一下卡死MYSQL

lihuan34 发表于 2012-11-9 11:11:48

路过顶一顶。

经过一段时间其他事务的处理,又回到要处理这个事情上面
页: [1]
查看完整版本: 10个百万级数据表需经过程序处理后整理导入到新表中