我正在做一个项目,要求我生成数十亿个唯一代码。目前,我使用带有InnoDB引擎和python的MariaDB生成随机唯一代码,每个生成周期插入5000个唯一代码批处理。
我的表结构:
row_id int --primary key + autoincrement
unique_code varchar(10) --unique
问题: 当我碰到5000亿个独特的代码时,Insert变得非常缓慢,我仍然需要生成多达30亿个代码。在创造这么多记录之前,我可以在几个小时内插入300-400百万个唯一代码。
感谢任何帮助,谢谢!
更新(19年1月22日) 回答Rick James'解决方案。 这是一些生成的代码示例:
RLXT$CPS1Y
Y4P$9K70WO
PKSTY9M$FR
T$0VEFL2B1
RX4$MEKVQL
我的服务器具有32GB的RAM和相对较快的SAS硬盘,我认为它足以满足我的需求(不是吗?)。
根据我的经验,TokuDB的插入速度较慢,在达到100m记录之前还比较费力,所以我当时去了InnoDB。
对于我之前提到的事务:是的,一次插入5000条记录。直到150m的代码,它是如此之快,之后我注意到速度随着记录的增长而逐渐下降。现在我达到800m的代码,插入周期(5000个记录)需要10到15秒。
我正在使用自动增量ID来对记录进行排序和标记,因为这些代码将被转移到另一个数据库进行打印(生产)。因此,我需要知道哪些代码已传输而哪些代码尚未传输。
我将等待进一步的回答,同时我将尝试Rick's suggestions。谢谢!
答案 0 :(得分:0)
尝试使用MySQL索引(如果您的服务器配置不是很好,则必须升级内存大小等)
答案 1 :(得分:0)
给我们看一下前10个值的样本。
这就是为什么您可能会“碰壁”的原因...索引可以(在一个级别上)分为两种类型:
连续的,例如AUTO_INCREMENT
值或TIMESTAMPs
,您可以按时间顺序甚至近似按时间顺序插入行。这些值插入到表或索引的“末尾”,并且仅命中BTree的最后一个块(或几个块)。通过将所有活动划分为几个块,可以执行很少的I / O。
随机数,例如UUID,MD5和其他“随机”值,大概包括您的值。在这种情况下,要插入表/索引的“下一个”值不太可能仍会缓存在RAM中。因此需要I / O。虽然表不是太大,但是所有索引块都可以保存在RAM中,因此几乎不需要I / O。但是,当索引大于缓存之后,添加“下一个”值的操作通常需要执行I / O。您的过程将会越来越慢。
该怎么办?
计划A:插入所有行后,在“ ”之后添加“随机”索引。添加索引将非常慢,但从长远来看可能会更快,因为它可以使用其他算法。
计划B:不要预先创建所有值。而是在需要时创建下一个。
计划C:购买足够的RAM以将“随机”索引完全保留在RAM中。 (计划将索引大小设为原来的两倍左右。)
计划D:您尝试过TokuDB吗?我希望它在陷入严重麻烦之前能够生存更长的时间。你的经验是什么。
您提到了交易。请详细说明。您是说每5000个代码在一次交易中都是INSERTed
吗?那可能是最佳的。
您使用什么字符集和排序规则作为唯一编号?您可能应该使用ascii和ascii_bin -为了提高速度并避免大小写折叠问题。
然后...这是关于如何生成它们的另一种想法。您将不必再检查唯一性,因为它们将生成唯一:
将您的10个字符的字符串视为以整数的base-95编码形式编码的数字。 (或者您允许使用许多不同的字符)。我们将顺序生成数字,将其转换为字符串,然后将其随机化。
“下一个”值被计算为超出“当前”值的随机值。随机值必须介于1到某个增量之间,该增量可能约为10亿(这取决于您最终想要多少个数字,字符集等)
将 INSERT
的5K(或其他任何数量)批处理成没有索引的MyISAM表。
完成后,请执行以下操作:
CREATE TABLE real (
id ... AUTO_INCREMENT, -- do you really need this??
random CHAR(10), NOT NULL CHARSET ascii COLLATE ascii_bin,
PRIMARY KEY(id), -- what for?
INDEX(random) -- uniqueness has been checked
INSERT INTO real (random)
SELECT random FROM myisam_table
ORDER BY RAND();
这是如何执行:
INSERT
将它们放入real
表中,随即创建顺序的ids
。注意:这将创建一个巨大的撤消表,因此请确保具有大量磁盘空间。
至于我对放弃id
,UNIQUE
等的评论,请提供有关您打算如何使用real
的信息,因此我可以同意或反对它们的使用。需要。
另一个计划
不预先生成值。取而代之的是,从大约14T的可能值中生成一个新值,检查是否存在重复,并在必要时生成另一个。在该计划中,表格会根据需要逐渐增长,而不必为最初构建表格而费力。取而代之的是,每当需要一个新的值时,就会花费一点努力(毫秒)。可以将其包装在“存储的函数”中,以方便用户使用。
该表只有一列unique_code CHAR(10) CHARSET ascii PRIMARY KEY
。