由於涉及大量數據,且須要必定的穩定性不能出錯,因此使用了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