批量生成序列号方案,in_array效率问题解决方案

 由于涉及大量数据,且须要必定的稳定性不能出错,因此使用了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

相关文章
相关标签/搜索