4

我有一个遗留系统,它使用一个表来排序编号。该表具有以下定义:

dbo.id_table
(
    table_name char(64) NOT NULL,
    id_type char(5) NOT NULL,
    data_type char(5) NOT NULL,
    next_id_number int NOT NULL,
    next_id_max char(15) NOT NULL
)
PRIMARY KEY CLUSTERED 
(
    table_name ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

此表在功能上等同于标识列。

以下是该表的使用方式: - 运行存储过程以获取表中 id 的下一个值。例如,

exec id_proc 'bryans_table', @some_int_value output

我正在寻找专家来回答以下问题:

将这样的设计与 SQL Server 2008 R2(当前以兼容模式运行,但计划在未来某个时候使用完整的 2008 R2)与使用常规标识列一起使用这样的设计对性能有何影响(尽可能具体) ? 这真的可以扩展吗?

我们看到很多争论是这个表,我想知道如果这些表被切换到标识列,可能会获得(或失去)哪种类型的性能提升?在这一点上,争论的来源尚不清楚。

(我不知道为什么原始设计中没有包含标识列——这是一个遗留数据库)

4

2 回答 2

8

根据定义,这样的设计意味着最多一个事务可以为表生成一个新序列(因为记录上的 X 锁正在递增)。换句话说,所有的 INSERT 都是序列化的(在第一个提交之前,没有新的 INSERT 可以继续)。性能坦克。

另一方面,IDENTITY 能够同时生成序列。

如果您被序列表卡住,您可以在单独的事务中生成新的 ID,需要单独连接到服务器,然后立即提交增量。或者批量生成(增量+1000)并在您的应用代码中处理分配的批次。后一种解决方案在减轻争用方面效果很好。但是您失去了事务一致性,增量发生在与 INSERT 不同的事务上,因此您会看到间隙、缺少序列等。但广告中的真相:IDENTITY 也有同样的问题(很多原因......)

于 2013-09-16T17:37:01.593 回答
0

您可以使用生成器表来获取序列 ID,而不会出现锁争用问题

——影子表

create table dummy_id (
  id int identity not null,
  dummy int not null
)

-- proc 显示使用情况

create proc dummy_id_gen(@newid int output) as
begin

begin tran
insert dbo.dummy_id (dummy) values (0)
select @newid = scope_identity()
rollback tran

end

-- 调用 proc 来测试它

declare @newid int
exec dummy_id_gen @newid = @newid output
select @newid as newid

这仍然存在生成的 id 一次只有 1 行的问题

于 2013-09-16T19:32:30.857 回答