Sql 向现有表中添加自动递增的列

Sql 向现有表中添加自动递增的列,sql,sql-server,tsql,auto-increment,Sql,Sql Server,Tsql,Auto Increment,鉴于: 我们有一个名为Events的表,目前包含大约1亿行: CREATE TABLE [dbo].[Events]( [Id] [uniqueidentifier] NOT NULL, [AggregateId] [uniqueidentifier] NOT NULL, [SourceType] [varchar](500) NOT NULL, [SourceId] [nvarchar](200) NOT NULL, [Timestamp] [datet

鉴于:

我们有一个名为Events的表,目前包含大约1亿行:

CREATE TABLE [dbo].[Events](
    [Id] [uniqueidentifier] NOT NULL,
    [AggregateId] [uniqueidentifier] NOT NULL,
    [SourceType] [varchar](500) NOT NULL,
    [SourceId] [nvarchar](200) NOT NULL,
    [Timestamp] [datetimeoffset](4) NOT NULL,
    [SerializedJson] [nvarchar](max) NOT NULL,
    [EventDataType] [varchar](500) NOT NULL,
 CONSTRAINT [PK_tblCepEvent_Id] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [UData]
) ON [UData] TEXTIMAGE_ON [UData]
GO

ALTER TABLE [dbo].[tblCepEvent] ADD  CONSTRAINT [DF_tblCepEvent_Id]  DEFAULT (newid()) FOR [Id]
GO
我们在SourceId列上还有一个非聚集索引

CREATE NONCLUSTERED INDEX [IX_tblCepEvent_SourceId] ON [dbo].[tblCepEvent] ([SourceId] ASC)
GO
期望:

我们希望添加一个新的整数列,该列包含与现有行的时间戳列顺序相同的自动递增值。背后的理念;我们正在处理大量数据,其中一些数据具有相同的时间戳值,因此我们希望能够按照插入的顺序对它们进行排序

尝试:

为了使自动递增的值与时间戳列的顺序相同,我删除了所有现有索引,然后在时间戳列上创建了一个升序聚集索引

-- 1 - drop primary key constraint
ALTER TABLE dbo.tblCepEvent DROP CONSTRAINT [PK_tblCepEvent_Id]
GO

-- 2- drop index on SourceId
DROP INDEX [IX_tblCepEvent_SourceId] ON dbo.tblCepEvent
GO

-- 3 - create a temporary asc clustered index on timestamp column
CREATE CLUSTERED INDEX [CIX_tblCepEvent_Timestamp] ON dbo.tblCepEvent ([Timestamp] ASC)
GO
然后我尝试创建新的专栏

-- 4 - create auto incremented column
ALTER TABLE dbo.tblCepEvent ADD OrderIndex BIGINT IDENTITY(1, 1) NOT NULL
GO
创建此列之后,我计划删除Timestamp列上的临时索引,然后返回并在SourceId列上创建主键和非聚集索引。 但不知何故,出现了一些错误,查询锁定了数据库,因此我不得不取消查询

在最后一次尝试之前,我在一组较小的数据(100万行)上测试了这种方法,并观察到它可以完成这项工作。
现在我的问题是:对于一个有超过1亿行的表,这是实现预期结果的好方法吗?您有什么建议可以更有效、更稳健地满足这一期望吗?

不要乱动删除和添加索引,这并不能保证满足您的要求。添加不带
标识的整数列
。通过
row\u number
使用所需的顺序将其填充为序列号,然后使用序列而不是
identity
来获取未来的新值,或者使用
ALTER TABLE。。。切换
方法使列成为仅元数据更改的
标识
列如果您在SSMS中尝试了相同的操作并检查了生成的脚本,您会看到它使用
标识创建了一个新表,将现有表中的所有行插入其中,然后重命名表。这对于大型表来说更具可伸缩性(也更安全)。使用
altertable。。。SWITCH
是一种更快的方法,它通过将一个表的数据页交换为另一个表来实现。这两个表必须具有相同的模式,但在您的示例中,不能依赖标识值来保持SELECT查询的顺序。出于性能原因,标识值是预先计算、缓存和批量分配的。当移动100米行时,所有这些机制都会起作用。您必须使用
ROW_NUMBER()OVER(ORDER BY timestamp)
在插入过程中生成ID值,并在插入后添加
IDENTITY
约束。不要乱丢和添加索引,这也不能保证满足您的要求。添加不带
标识的整数列
。通过
row\u number
使用所需的顺序将其填充为序列号,然后使用序列而不是
identity
来获取未来的新值,或者使用
ALTER TABLE。。。切换
方法使列成为仅元数据更改的
标识
列如果您在SSMS中尝试了相同的操作并检查了生成的脚本,您会看到它使用
标识创建了一个新表,将现有表中的所有行插入其中,然后重命名表。这对于大型表来说更具可伸缩性(也更安全)。使用
altertable。。。SWITCH
是一种更快的方法,它通过将一个表的数据页交换为另一个表来实现。这两个表必须具有相同的模式,但在您的示例中,不能依赖标识值来保持SELECT查询的顺序。出于性能原因,标识值是预先计算、缓存和批量分配的。当移动100米行时,所有这些机制都会起作用。您必须使用
ROW\u NUMBER()OVER(按时间戳排序)
在插入期间生成ID值,然后添加
IDENTITY
约束