【发布时间】:2012-06-13 11:43:26
【问题描述】:
我正在尝试生成 16 000 000 个唯一随机数(10 位:范围 1 000 000 000 - 9 999 999 999)并将它们插入一个空表(如果不为空,则填满此表)。
桌子:
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 小时...... 有什么办法可以优化吗?
【问题讨论】:
-
实际上,表中的记录越多,插入的速度就越慢,因为随着表填满,您将逐渐遇到更多的冲突,因此您对 33 小时的线性估计过于乐观。
-
你说得对,它非常乐观。 lanzz 提到的更快的解决方案需要 0.9 秒和 20k 条记录。所以 16M - 15 分钟,但最终需要 3 小时。
-
您应该查看事务 - 开始事务、循环并插入,然后在最后提交或每 400 万行左右提交一次。此外,您应该避免执行 select count(*) 并使用变量作为计数器,例如而我 dev.mysql.com/doc/refman/5.0/en/commit.html
标签: mysql performance