由于涉及大量数据,且须要必定的稳定性不能出错,因此使用了mysql的事物。php
所谓事物简单理解就是要么包含的全部sql所有执行,要么一条都别执行。mysql
这里我用的是tp5框架,不用框架思路也是同样的。sql
核心主要是事物+批量录入卡号+验证卡密码惟一性。下面有优化版。数据库
public function setCard($data,$id){ Db::startTrans();//准备事物 try{ $card = model('CardType')->getOneData(' * ',['id'=>$data['cardtype']]);//获取卡分类 $table = 'card_'.$card->mark; $card_id = Db::table($table)->field('max(id) id')->find();//获取最大卡号 //准备数据 $sql = "INSERT INTO `{$table}` (`id`,`password`,`product_id`) VALUES "; $i = $data['num']; $card_id = empty($card_id['id']) ? 10000000 : $card_id['id']; $str = ''; $old_psw = array(); for ($i;$i>0;$i--){ if ($i != $data['num'])$str .= ','; ++$card_id; $t = true; while ($t){//处理可能重复的卡号 $psw = rand(10000001,99999999).rand(10000001,99999999); if (!in_array($psw,$old_psw)){ if (!Db::table($table)->field('id')->where('password = '.$psw)->find()){ $t = false; $old_psw[] = $psw; } } } $str .= '('.$card_id.','.$psw.','.$id.')'; } $sql = $sql.$str; unset($old_psw); Db::query($sql); unset($sql); unset($str); Db::commit(); } catch (\Exception $e) { // 回滚事务 Db::rollback(); return false; } return true; }
由于用上面方案以后2万条数据大概须要四五分钟才能处理完,领导说没事,我忍不了!(这小暴脾气..)数组
想一想都已经old_psw了为啥不提早把数据库查询直接拉出来,不必每次都对比。而后就有了以下代码。框架
$old_data = Db::table($table)->field('password')->select(); $old_psw = array_column($old_data,'password');//存入数组 unset($old_data); for ($i;$i>0;$i--){ if ($i != $data['num'])$str .= ','; ++$card_id; $t = true; while ($t){//处理可能重复的卡号 $psw = rand(10000001,99999999).rand(10000001,99999999); if (!in_array($psw,$old_psw,true)){ $t = false; $old_psw[] = $psw; } } $str .= '('.$card_id.','.$psw.','.$id.')'; }
代码上下跟上面的同样,就不反复贴了。而后发现这么处理以后速度竟然慢了N倍。。优化
笨方法,排除吧!microtime()上场! 各类地方打标记以后发现,竟然是in_array在拖后腿,in_array在处理大量数据的时候效率极其低下,各类查资料发现in_array有第三个参数,即严格匹配,而后加了个true。。这下2w条2,3秒就处理完了。code