生成16M唯一随机数

时间:2012-06-13 11:43:26

标签: mysql performance

我正在尝试生成16 000 000个唯一随机数(10位数:范围1 000 000 000 - 9 999 999 999)并将它们插入空表(如果不是空的话,请填写此表)。< / p>

表格:

CREATE TABLE `codes` (
`code_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`code` bigint(20) UNSIGNED NOT NULL,
`is_used` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`code_id`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

...和功能:

DELIMITER $$

CREATE DEFINER=`root`@`localhost` FUNCTION `codes`(`minRange` BIGINT UNSIGNED, `maxRange` BIGINT UNSIGNED, `_amount` BIGINT UNSIGNED) RETURNS tinyint(1)
MODIFIES SQL DATA
BEGIN
DECLARE pick BIGINT;


while (SELECT count(*) FROM codes) < _amount do
begin
SET pick = minRange + FLOOR(RAND() * (maxRange - minRange + 1));
INSERT IGNORE INTO codes (code) VALUES (pick);

end;
end while;

RETURN 1;
END$$

DELIMITER ;

-- call: SELECT codes(1000000000,9999999999,16000000);

该功能非常慢:产生20k行需要2.5分钟,所以16M - 大约33小时...... 有没有办法优化它?

4 个答案:

答案 0 :(得分:2)

你所要求的是矛盾。如果16M数字是唯一的,那么它们不是随机的。想一想:一个真正的10位数随机数的概率为1 / 9E9是任何给定的数字。然而,你的第16个数字可能是159999,999个数字之一,而1 / 983,000,001概率是剩下的数字之一。你应该总是期待重复。在1B中,16M中大约有1%。

所以我的建议是生成(16M +一点)随机数,做一个独特的排序;截断到16M然后随机排序。我的Q&amp; D要做到这一点:

php -r 'for( $i=0;$i<16500000;$i++) echo mt_rand(100000000, 999999999),"\n";'\
  | sort -u | head -16000000 | sort -R > /tmp/loadfile.lst
在我4岁的笔记本电脑上花了7分多钟。在现代四核桌面上,它将更快很多。我使用PHP-CLI,因为我在笔记本电脑上使用它,mt_rand例程很好。你可以做一个3班轮-Cs编程或任何语言。正如Zercms所说,只要在加载之前禁用索引并在之后重新启用,负载就会很快。您还只需加载列code

享受。

答案 1 :(得分:1)

我能想到的最快的方法是生成包含唯一数字的纯文本文件并使用LOAD DATA INFILE

此外,您需要在开始加载数据之前使用ALTER TABLE禁用密钥,并在此之后启用

答案 2 :(得分:1)

您为插入的每个随机数运行SELECT count(*)。一个简单的优化就是尝试在没有检查的情况下填充16000000个随机数,然后查看实际插入的数量,从头开始重复添加的剩余数量。

答案 3 :(得分:0)

也许你应该尝试不是通过MySQL生成你的数字,而是通过PHP生成你的数字。 PHP mt_rand()确实生成了更好的随机值,您可以在数组中填写您的值,并直接通过in_array()检查它是否已经存在。

此外,由于每次都必须更新表索引,MySQL的速度会大大降低,如果需要在MySQL中执行,可能应该在生成数字时禁用它。