您的位置:首页 > 编程语言 > PHP开发

ThinkPHP操作MySQL删除大量数据的优化

2016-10-18 22:19 211 查看
我对有一个8万条数据的表进行了一次去重操作,其中有将近6万条的重复数据需要被删除。考虑到可能会产生对数据库的高IO操作,我选择进行删除算法的优化。

第一个函数

获取要删除的id数组

从原来的sql数据文档里面读取出来这8万条数据并保存到数组中。为了防止数据溢出,我选择逐行读取,数据的大小分4k储存.

读取过之后进行了三次正则匹配

第一次正则匹配,匹配出长度为十位的学号,保存到数组里面。

第二次正则匹配,匹配出所有包含汉字的第一个符合项。

第三次正则匹配,匹配出长度为十八位的身份证号。在匹配身份证号的时候要注意最后一位可能是x,所以正则表达式我写的是前十七位为数字,后一位自行判断是数字还是字母。

所有的数据都被读取出来之后,我进行了一个非空判断,对当行的数据进行插入操作,然后,继续读取下一行,当所有的行都没读取完之后要进行文件的关闭操作。

与此同时,我在函数的开始和函数的结束,加上了时间判断符,最后打印出时间的消耗,大概每次执行函数的时间在66秒左右。

第二个函数

分批次删除数据

将重复的id保存下来。

通过idcode字段将相同的身份证号按组排列起来,并且选出组中最小的那个id,相当于不重复的唯一的一条数据,然后用foreach循环。

将字符串组合成逗号连接的数组。按每1000条为一个组进行删除。这样做的好处是防止在同时删除上万条数据的时候,数据库崩溃或者是操作超时。

public function getArray()
{
set_time_limit(120);
$DB = M('code');
$handle = @fopen("C:/Users/Administrator/Desktop/xcu/UserData/user.sql", "r");
$t1 = microtime(true);
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
if (preg_match('/[\d]{10}\b/', $buffer, $match)) {
$array['sid'] = $match[0];
if (preg_match('/[\x7f-\xff]+/', $buffer, $match)) {
$array['name'] = iconv('gbk', 'utf-8', $match[0]);
if (preg_match('/\d{17}[\d|X|x]/', $buffer, $match)) {
$array['idcode'] = $match[0];
}
}
}
if (!empty($array)) {
$DB->data($array)->add();
}
}
fclose($handle);
}
$t2 = microtime(true);
echo '耗时' . round($t2 - $t1, 3) . '秒';
}

public function delData()
{
set_time_limit(120);
$DB = M('code');
$res = $DB->field('min(id) as id')->group('idcode')->select();
$t1 = microtime(true);
$arr = "";
$count = 0;
foreach ($res as $val) {
$count++;
//var_dump($val['id'].'<br>');
$arr.= ",".$val['id'];
if ($count % 1000 == 0){
echo substr($arr,1).'<br>';
$map["id"] = array('in', substr($arr,1));
$sqlres = $DB->where($map)->delete();
if ($sqlres){
echo "批次删除成功!";
}
$arr = "";
}
}
$t2 = microtime(true);
echo '耗时' . round($t2 - $t1, 3) . '秒';
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  thinkphp 数据库