Php 生成一百万个唯一的随机12位数字
我需要为一个scratch卡应用程序生成接近一百万(100批10000个数字)的唯一和随机12位代码。此过程将重复,每次都需要生成相同数量的代码 此外,生成的代码需要输入到数据库中,以便消费者稍后在我的网站上输入时可以对其进行验证。我正在使用PHP和Mysql来实现这一点。这些是我正在遵循的步骤Php 生成一百万个唯一的随机12位数字,php,mysql,optimization,random,unique,Php,Mysql,Optimization,Random,Unique,我需要为一个scratch卡应用程序生成接近一百万(100批10000个数字)的唯一和随机12位代码。此过程将重复,每次都需要生成相同数量的代码 此外,生成的代码需要输入到数据库中,以便消费者稍后在我的网站上输入时可以对其进行验证。我正在使用PHP和Mysql来实现这一点。这些是我正在遵循的步骤 获取有关批数和每批代码的管理员输入 使用for循环使用 mt_兰特(1000000000009999999999) 每次生成数字时检查是否存在重复 在数据库中,如果不添加到结果变量,则重新生成 如果唯一
mt_兰特(1000000000009999999999)
$totalabels=$numBatch*$numLabelsPerBatch;
//下载文件名
$fileName=$customerName.“\u scratchcodes\u”。日期(“Ymdhs”)。“.csv”;
$flag=false;
$generatedCodeInfo=array();
//下载的标题
标题(“内容处置:附件;文件名=\”$filename\”);
标题(“内容类型:application/vnd.ms excel”);
$codeObject=新代码();
//获取新批号
$batchNumber=$codeObject->getLastBatchNumber()+1;
$random=array();
对于($i=0;$i<$totalAbels;$i++){
做{
$random[$i]=mt_rand(1000000000009999999999);//考虑到数据库的增长,需要对此进行优化以减少冲突
}而(isCodeNotUnique($random[$i],$db));
$codeObject=新代码();
$codeObject->UID=$random[$i];
$codeObject->customerName=$customerName;
$codeObject->batchNumber=$batchNumber;
$generatedCodeInfo[$i]=$codeObject->addCode();
//更改下一批的批号
如果($i==($numLabelsPerBatch-1)){$batchNumber++;}
//$generatedCodeInfo[i]=数组(“UID”=>10001,“OID”=>$random[$i]);
如果(!$flag){
//将列名显示为第一行
回声内爆(“\t”,数组_键($generatedCodeInfo[$i]))。“\n”;
$flag=true;
}
//过滤数据
数组_walk($generatedCodeInfo[$i],'filterData');
echo内爆(“\t”,数组值($generatedCodeInfo[$i]))。“\n”;
}
函数filterData(&$str)
{
$str=preg_replace(“/\t/”、“\\t”、$str);
$str=preg\u replace(“/\r?\n/”、“\\n”、$str);
如果(strstrstr($str,“'))$str=''''''''''''.str_替换('''''','''''',''''''.''''.''.'',$str)。''''';
}
函数isCodeNotUnique($random){
$codeObject=新代码();
$codeObject->UID=$random;
如果(!empty($codeObject->getCodeByUID())){
返回true;
}
返回false;
}
现在这需要很长时间来执行,我认为这不是最佳的
insert
语句插入批处理的内容:
insert into yourtable (bignumber) values (1), (2), ..., (n)
检查MySQL的max_allowed_packet
设置,看看它是否能够一次性接收完整的sql语句
实施回退计划,以防在插入过程中仍然发现重复值(错误处理和编号重新生成)
2) MySQL在程序方面不是很好,所以我会坚持使用外部语言,比如php
3) 在包含随机数的字段上添加唯一索引。如果您试图插入重复记录,MySQL将阻止它并抛出一个错误。它真的很快
4) 根据实际使用的表引擎(innodb、myisam等)、其配置和操作系统,表的大小可能会受到某些限制。请参阅此处的问题,以获得更详细的答案(请选择投票最多的答案,而不是被接受的答案)。您可以执行以下操作:
$random = getExistingCodes(); // Get what you already have (from the DB).
$random = array_flip($random); //Make them into keys
$existingCount = count($random); //The codes you already have
do {
$random[mt_rand(100000000000,999999999999)] = 1;
} while ((count($random)-$existingCount) < $totalLabels);
$random = array_keys($random);
$random=getExistingCodes();//从数据库中获取您已经拥有的内容。
$random=数组翻转($random)//把它们做成钥匙
$existingCount=计数($random)//您已有的代码
做{
$random[mt_rand(1000000000009999999999)]=1;
}而((计数($random)-$existingCount)<$totalabels);
$random=数组_键($random);
当您生成一个重复的数字时,它只会覆盖该键,而不会增加计数
要插入,您可以启动一个事务,并根据需要执行尽可能多的插入。MySQL将尝试在一个事务中优化所有操作。下面是一个查询,它可以生成100万个不重复的伪随机数:
select cast( (@n := (13*@n + 97) % 899999999981)+1e11 as char(12)) as num
from (select @n := floor(rand() * 9e11) ) init,
(select 1 union select 2) m01,
(select 1 union select 2) m02,
(select 1 union select 2) m03,
(select 1 union select 2) m04,
(select 1 union select 2) m05,
(select 1 union select 2) m06,
(select 1 union select 2) m07,
(select 1 union select 2) m08,
(select 1 union select 2) m09,
(select 1 union select 2) m10,
(select 1 union select 2) m11,
(select 1 union select 2) m12,
(select 1 union select 2) m13,
(select 1 union select 2) m14,
(select 1 union select 2) m15,
(select 1 union select 2) m16,
(select 1 union select 2) m17,
(select 1 union select 2) m18,
(select 1 union select 2) m19,
(select 1 union select 2) m20
limit 1000000;
工作原理
它首先生成一个带有0的随机整数值n
插入1e6/15次
检查COUNT(*)
查看您是否有一百万。执行此操作,直到表格显示为一百万行:
INSERT IGNORE INTO x (v) VALUES
(FLOOR(1e12*RAND());
注:
ZEROFILL
@n := floor(rand() * 9e11)
@n := (13*@n + 97) % 899999999981
CREATE TABLE x (v BIGINT(12) ZEROFILL NOT NULL PRIMARY KEY); INSERT IGNORE INTO x (v) VALUES (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND()), (FLOOR(1e12*RAND());
INSERT IGNORE INTO x (v) VALUES (FLOOR(1e12*RAND());
<?php // Does mt_rand() repeat? TryMT(100); TryMT(100); TryMT(1000); TryMT(10000); TryMT(1e6); TryMT(1e8); TryMT(1e10); TryMT(1e12); TryMT(1e14); function TryMT($max) { $h = []; for ($j = 0; $j<$max; $j++) { $v = mt_rand(1, $max); if (isset($h[$v])) { echo "Dup after $j iterations (limit=$max)<br>\n"; return; } $h[$v] = 1; } }
Dup after 7 iterations (limit=100)<br> Dup after 13 iterations (limit=100)<br> Dup after 29 iterations (limit=1000)<br> Dup after 253 iterations (limit=10000)<br> Dup after 245 iterations (limit=1000000)<br> Dup after 3407 iterations (limit=100000000)<br> Dup after 29667 iterations (limit=10000000000)<br> Dup after 82046 iterations (limit=1000000000000)<br> Dup after 42603 iterations (limit=1.0E+14)<br>