【发布时间】:2016-11-01 09:54:01
【问题描述】:
我需要为刮刮卡应用程序生成接近一百万(100 批 10000 个数字)唯一且随机的 12 位代码。此过程将重复进行,并且每次都需要生成相同数量的代码。
还需要将生成的代码输入到数据库中,以便稍后在消费者在我的网站上输入此代码时对其进行验证。我正在使用 PHP 和 Mysql 来执行此操作。这些是我正在遵循的步骤
获取有关批次数量和每批次代码的管理员输入
使用 for 循环生成代码
mt_rand(100000000000,999999999999)每次生成数字时检查是否存在重复 在数据库中,如果不添加到结果变量中,则重新生成。
如果唯一,则将生成的数字保存在数据库中
在所需的代码数量上重复 b、c 和 d
在 csv 中向管理员输出代码
使用的代码(删除了大部分 cmets 以使其不那么冗长,因为我之前已经解释了这些步骤):
$totalLabels = $numBatch*$numLabelsPerBatch;
// file name for download
$fileName = $customerName."_scratchcodes_" . date('Ymdhs') . ".csv";
$flag = false;
$generatedCodeInfo = array();
// headers for download
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Content-Type: application/vnd.ms-excel");
$codeObject = new Codes();
//get new batch number
$batchNumber = $codeObject->getLastBatchNumber() + 1;
$random = array();
for ($i = 0; $i < $totalLabels; $i++) {
do{
$random[$i] = mt_rand(100000000000,999999999999); //need to optimize this to reduce collisions given the databse will be grow
}while(isCodeNotUnique($random[$i],$db));
$codeObject = new Codes();
$codeObject->UID = $random[$i];
$codeObject->customerName = $customerName;
$codeObject->batchNumber = $batchNumber;
$generatedCodeInfo[$i] = $codeObject->addCode();
//change batch number for next batch
if($i == ($numLabelsPerBatch-1)){$batchNumber++;}
//$generatedCodeInfo[i] = array("UID" => 10001,"OID"=>$random[$i]);
if(!$flag) {
// display column names as first row
echo implode("\t", array_keys($generatedCodeInfo[$i])) . "\n";
$flag = true;
}
// filter data
array_walk($generatedCodeInfo[$i], 'filterData');
echo implode("\t", array_values($generatedCodeInfo[$i])) . "\n";
}
function filterData(&$str)
{
$str = preg_replace("/\t/", "\\t", $str);
$str = preg_replace("/\r?\n/", "\\n", $str);
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
function isCodeNotUnique($random){
$codeObject = new Codes();
$codeObject->UID = $random;
if(!empty($codeObject->getCodeByUID())){
return true;
}
return false;
}
现在这需要很长时间才能执行,我认为这不是最佳选择。
如何优化才能快速生成唯一随机数?
如果用 mysql 或其他方式而不是 php 生成数字会更快吗?如果是,我该怎么做?
当 db 开始增长时,步骤 b 中的重复检查将非常耗时,那么我该如何避免呢?
mysql中的行数有限制吗?
注意:数字需要在应用程序生命周期内的所有批次中唯一。
【问题讨论】:
-
数据库中是否已有代码?如果没有,您可以在 PHP 中生成所有代码并在单个事务中将它们推送到 MySQL。在 PHP 中检查重复项可能会更快。在现代机器上,100 万个数字基本上算不了什么。 PHP 和 MySQL 都可以轻松搞定。
-
3) 如果您的数据库被正确索引,则不会; 4)对于这个相对较小的数据量,没问题,几千亿是大的,一百万不是
-
@apokryfos 不是今天,但是一旦我生成了第一批,这将继续增长。您能否详细说明“如果不是,您可以在 PHP 中生成所有代码并在单个事务中将它们推送到 MySQL。在 PHP 中检查重复可能会更快。”
-
我会做影子的方法。 1) 生成 100 个随机 3 位数字(批次)(范围 100 - 999)。 2) 为每个批次生成 10000 个唯一数字(范围 0 - 999999999)。不会有很多碰撞,所以它会很快。将批次 ID 与 9 位批次号结合起来,得到一个 12 位的唯一编号。
-
这里的完整实现:pastebin.com/Wmh9ueZ1。它一次生成并保存一批,因此不应该存在内存问题。修改常量以获取生成的完整值并保存。在我的系统上,数据库保存非常慢(每批 30 秒),但它是“双仓鼠驱动”电脑 :)
标签: php mysql optimization random unique