现在的位置: 首页 > 综合 > 正文

如何快速生成100万不重复的8位编号

2013年08月05日 ⁄ 综合 ⁄ 共 3578字 ⁄ 字号 评论关闭
文章目录

最近在论坛看到有人问,如何快速生成100万不重复的8位编号,对于这个问题,有几点是需要注意的:

1.    如何生成8位随机数,生成的数越随机,重复的可能性当然越小

2.    控制不重复

3.    考虑性能

针对这个问题,我写了如下的示例来解决,希望能为有这类需求的人提供指导

 

生成100万条8位不重复数据的示例

USE tempdb

GO

 

-- 创建测试表

CREATE TABLE tb(id char(8))

 

-- 创建用于自动过滤重复值的唯一索引

CREATE UNIQUE INDEX IX_tb ON tb(id)

WITH IGNORE_DUP_KEY

GO

 

-- 测试数据插入的处理时间, 记录开始处理的时间点

DECLARE @dt datetime

SET @dt = GETDATE()

 

-- 插入随机数据

SET NOCOUNT ON

DECLARE @row int

SET @row = 1000000  -- 设置总记录数

WHILE @row >0

BEGIN

    -- 显示提示信息, 表示还需要插入多行数据

    RAISERROR('need %d rows', 10, 1, @row) WITH NOWAIT

 

    -- 插入随机的位编码数据

    SET ROWCOUNT @row

    INSERT tb SELECT

        id = RIGHT(100000000 + CONVERT(bigint, ABS(CHECKSUM(NEWID()))), 8)

    FROM syscolumns c1, syscolumns c2

    SET @row = @row - @@ROWCOUNT

END

 

-- 显示插入数据使用的时间

SELECT BeginDate = @dt, EndDate = GETDATE(),

    Second = DATEDIFF(Second, @dt, GETDATE()),

GO

 

-- 显示最终的结果记录是否正确

SELECT COUNT(*) FROM tb

GO

 

-- 删除测试

DROP TABLE tb

 

解决中用到的技巧:

1.    控制产生的数据不重复,直接使用唯一索引中的 IGNORE_DUP_KEY 选项,使插入数据中的重复值自动过滤,避免手工处理重复

2.    使用 CHECKSUM 配合 NEWID() 函数,使生成的数据尽量随机,一般生成随机数会考虑使用 RAND() 函数,但这个函数是产生伪随机值,用下面的语句测试一下,会发现产生的数据全部是一样的,这不适用于想批量生成多个随机数,而NEWID() 函数生成的是GUID,基本上不会有重复的,再通过CHECKSUM将其转化成数字,这样产生重复的可能性会比较小

SELECT TOP 10

    RAND()

FROM sysobjects

3.    在效率控制,使用循环+批量生成的方式,而不是传统的逐个生成。在SQL Server中,每个插入语句都会有一个内部的事务处理,如果逐条插入,则事务的开销太大,效率势必非常低;不考虑一次性生成100万数据,一则因为生成的数据可能有重复的,去掉重复就没有100万了,二则一次性生成100万数据,消耗的内存和CPU资源也很高,一般的电脑可能承受不住

 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1099215


[收藏到我的网摘]   邹建发表于 2006年08月20日 11:28:00
 特别推荐:

 

 #  atomic_age 发表于2006-08-21 21:54:00  IP: 211.100.21.*
TrackBack来自《如何快速生成100万不重复的8位编号?》

如何快速生成100万不重复的8位编号

 #  seLecT. 发表于2006-08-24 17:35:00  IP: 211.100.21.*
TrackBack来自《如何快速生成100万不重复的8位编号》

如何快速生成100万不重复的8位编号

 #  醉梦流仙 发表于2006-08-21 15:53:00  IP: 218.107.55.*
“如何快速生成100万不重复的8位编号”
不是我要钻牛角尖,这个要求,数字0-1000000也满足要求啊,呵呵,如果不特别说明的话。

 #  是劫是缘 发表于2006-08-21 18:29:00  IP: 221.226.115.*
感觉很搞笑,不知道楼主想说什么?
请问楼主,示例执行了多长时间?

 #  qiandeng 发表于2006-08-21 18:43:00  IP: 222.66.38.*
这个还是实用的,很多时候需要的是真正随机

 #  allyesno 发表于2006-08-21 18:54:00  IP: 59.34.142.*
如果是验证码0-100000也行了 只要加上干扰信息

 #  atomic_age 发表于2006-08-21 21:37:00  IP: 221.200.164.*
我给个方法。
假设我要产生从10000000 - 99999999妈即在产生一百的随机数。可以建立一个表table1,这个表有两个字段,一个是所产生的随机数字段(int型),另外一个是和这个字段同类型的字段。
使用9999999 - 1000000 =89999999 整除 9 = 89(舍去)。然后从10000000开始循环1000000次,从10000000开始每一次加89,
即10000000、10000089、10000178...
然后每循环一次,使用newid生成一个随即数,将这两个数做为值插入tabl1中。这样,table1就有1百万条记录了,不过是随机值是顺序的。但由于第二个字段是随机的,因此,只要按第二个字段排序,第一个字段上的值就是随机的。

这样做不用检查重复值就可以保证得到1000000个无重复的随机数。而且它们是均匀分布在10000000到99999999之间。
当然,也可以随机变化89的步长,使其更加随机。
这样做还有一个好处,可以分批地生成记录,然后一起插入表中。如一次产生1000条这样的记录,插入后再产生下一条记录。这样只要循环1000次就可完成。

如果这个方法有什么问题可以通过asklining@126.com和我联系。

 #  atomic_age 发表于2006-08-21 21:39:00  IP: 221.200.164.*
我给个方法。
假设我要在10000000 - 99999999之间产生一百万个不重复的随机数。可以建立一个表table1,这个表有两个字段,一个是所产生的随机数字段(int型),另外一个是和这个字段同类型的字段。
使用9999999 - 1000000 =89999999 整除 9 = 89(舍去)。然后从10000000开始循环1000000次,从10000000开始每一次加89,
即10000000、10000089、10000178...
然后每循环一次,使用newid生成一个随即数,将这两个数做为值插入tabl1中。这样,table1就有1百万条记录了,不过是随机值是顺序的。但由于第二个字段是随机的,因此,只要按第二个字段排序,第一个字段上的值就是随机的。

这样做不用检查重复值就可以保证得到1000000个无重复的随机数。而且它们是均匀分布在10000000到99999999之间。
当然,也可以随机变化89的步长,使其更加随机。
这样做还有一个好处,可以分批地生成记录,然后一起插入表中。如一次产生1000条这样的记录,插入后再产生下一条记录。这样只要循环1000次就可完成。

如果这个方法有什么问题可以通过asklining@126.com和我联系。

 #  lance 发表于2006-08-21 23:07:00  IP: 60.232.165.*
用个循环 把数组打乱,效果是不是也一样?

 #  myan 发表于2006-08-21 22:28:00  IP: 219.236.56.*
楼主是数据库专家,用数据库的方法来解决问题是无可厚非。如果让我来做的话,我会用STL里的shuffle算法来做。对于100万这样的规模来说,应该是轻而易

抱歉!评论已关闭.