Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请教:SQL Server版批量生成时会出现重复ID #74

Open
cyy201 opened this issue Aug 24, 2023 · 2 comments
Open

请教:SQL Server版批量生成时会出现重复ID #74

cyy201 opened this issue Aug 24, 2023 · 2 comments

Comments

@cyy201
Copy link

cyy201 commented Aug 24, 2023

SQL Server版像select表insert到另外一表,生成的ID会有很多重复的,用RAND()还有一个问题会导致生成ID是乱序的,请问这个要怎么解决?用C#版就没这个问题

@yitter
Copy link
Owner

yitter commented Aug 26, 2023

你这个场景不太适合用SQL版本。建议用C#版。

@liudegang123
Copy link

liudegang123 commented Dec 14, 2023

你这个场景不太适合用SQL版本。建议用C#版。

我在你的基础上改进了一下 用循环序列号的方法,希望大神可以指教一下 @yitter


-- Author: lou <Author,,Name>
-- =============================================
-- Author: lou
-- Create date:2023/12/14 19:49:41
-- Description: 雪花id序列号, Yitter.IdGenerator Sql版本改进所需要的
---属性说明
---START: 起始值
---INCREMENT: 增量(步长)
---MINVALUE: 最小值
---MAXVALUE: 最大值, 根据 dbo.Fn_NextSnowId 的 SeqBigLength 计算得来, 2^SeqBigLength - 1 等于 当前是 7 2^7-1 = 128 - 1 = 127
---CYCLE: 循环 到最大值后重新从最小值开始
-- =============================================
CREATE SEQUENCE [dbo].[SnowFlakeIdSequence]
AS [bigint]
START WITH 5
INCREMENT BY 1
MINVALUE 5
MAXVALUE 127
CYCLE
CACHE
GO

-- Author: lou <Author,,Name>
-- =============================================
-- Author: lou 禁止修改 禁止修改禁 止修改
-- Create date:2023/12/14 19:49:41
-- Description: 雪花id配置视图
---属性说明
--- WorkerId: [1,8]最大值 2^@WorkerIdBigLength-1
--- WorkerIdBigLength: 规则约束:@WorkerIdBigLength+@SeqBigLength<23
--- SeqBigLength: 建议不小于6,在当前SQL版本中,@SeqBigLength 决定随机数的最大值(未采用自增数,这需要数据表记录Seq值)
--- BaseTimeTimeTick: 基础时间毫秒时间戳 1582165202020
--- 计算方法如下:
--- select CONVERT(BIGINT,DATEDIFF(MI,'1970-01-01 00:00:00.000', '2020-02-20 02:20:02.020')) * 60000
--- + DATEPART(S,'2020-02-20 02:20:02.020') * 1000
--- + DATEPART(MS, '2020-02-20 02:20:02.020')
-- =============================================
ALTER VIEW [dbo].[V_NextSnowIdConfig]
as
select
0 as WorkerId, -- 最大值 2^@WorkerIdBigLength-1 可以不 -1 详见雪花id算法说明
3 as WorkerIdBigLength, -- 规则约束:@WorkerIdBigLength+@SeqBigLength<23, WorkerIdBigLength = 3 (2^3) -1 支持 [1,7] 的 WorkerId
7 as SeqBigLength, -- 建议不小于6,在当前SQL版本中,@SeqBigLength 决定随机数的最大值(未采用自增数,这需要数据表记录Seq值)
1582165202020 as BaseTimeTimeTick --基础时间毫秒时间戳

GO

-- Author: lou <Author,,Name>
-- =============================================
-- Author: lou
-- Create date:2023/12/14 19:49:41
-- Description: 获取雪花id方法, Yitter.IdGenerator Sql版本的改进
-- Example: select dbo.Fn_NextSnowId(NEXT VALUE FOR [SnowFlakeIdSequence])
---属性说明
---@CurrentSeqNumber: 序列号 通过 NEXT VALUE FOR [SnowFlakeIdSequence] 获得
------- SnowFlakeIdSequence 说明:
------- 最小值: 5 , 0 - 4是保留位 其中1-4是时间回拨相应预留位,0是手工新值预留位
------- 最大值: 127 2^SeqBigLength - 1 得来的
-- =============================================
ALTER FUNCTION [dbo].[Fn_NextSnowId]
(
--@randomseed float-- 生成ID的函数,需要有一个随机数,在调用时,传入系统函数 rand() 即可
--原来的是随机数,有概率会重复 所以使用循环的序列号
@CurrentSeqNumber int --循环自增序列号 NEXT VALUE FOR [SnowFlakeIdSequence]
)
RETURNS bigint
AS
BEGIN
declare @currenttime bigint
declare @TimeTick bigint
declare @WORKERID int
declare @WorkerIdBigLength int
declare @SeqBigLength int
declare @BaseTimeTimeTick bigint
---Begin: 以下是需要初始化的参数,请确保 @WorkerIdBigLength 和 @SeqBigLength 的设置值跟其它应用程序相同
--set @WORKERID = 1 -- 最大值 2^@WorkerIdBigLength-1
--set @WorkerIdBigLength = 3 -- 规则约束:@WorkerIdBigLength+@SeqBigLength<23
--set @SeqBigLength = 7 -- 建议不小于6,在当前SQL版本中,@SeqBigLength 决定随机数的最大值(未采用自增数,这需要数据表记录Seq值)
--set @BaseTimeTimeTick = 1582136402000
---从配置视图中获取
select @WORKERID = WorkerId,
@WorkerIdBigLength = WorkerIdBigLength,
@SeqBigLength = SeqBigLength,
@BaseTimeTimeTick = BaseTimeTimeTick
from V_NextSnowIdConfig
---End
---当前时间戳(毫秒单位)
set @currenttime = CONVERT(BIGINT,DATEDIFF(MI,'1970-01-01 00:00:00.000', GETUTCDATE())) * 60000 + DATEPART(S,GETUTCDATE()) * 1000 + DATEPART(MS, GETUTCDATE())
---用当前时间戳减去基础时间,得出ID的时间差部分
set @TimeTick=@CurrentTime-@BaseTimeTimeTick
---生成ID
---雪花ID的序列数 = 5至2^SeqBigLength-1之间的随机数。 (5 + round((POWER(2, @SeqBigLength)-1) * rand(), 0)
---最后的数本来用的是随机数,但是存在重复的可能 所以改成循环序列号
return @TimeTick * POWER(2, @WorkerIdBigLength + @SeqBigLength)
+ @WORKERID * POWER(2, @SeqBigLength)
+ (@CurrentSeqNumber) --通过自增序列来生成 SnowFlakeIdSequence 已经控制 5 - 127 循环
--+ (5 + round((POWER(2, @SeqBigLength)-1) * @randomseed, 0)) --本来用随机数 但是也有概率重复 所以用 循环序列号 SnowFlakeIdSequence
END
GO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants