在我们的生产系统(SQL Server 2008 / R2)中,有一个表格,用于存储生成的文档。
文档有引用(varchar
)和sequence_nr(int
)。可以多次生成文档,并且每次迭代都保存在该表中,递增序列号。此外,每条记录都有一个数据列(varbinary
)和一个时间戳以及一个用户标记。
查询此表的唯一原因是在以后和插入期间进行审计。
该表的主键聚集在reference
和sequence_nr
列上。
正如您可能猜到的那样,文档的生成以及表格中的数据(因为文档可以在以后再次生成)不会按顺序增长。
我在表中的插入开始超时后意识到这一点。
使用存储过程执行插入。存储过程确定给定引用的当前最大sequence_nr
,并使用下一个sequence_nr
插入新行。
我很确定聚簇索引选择不当导致超时问题,因为记录将被插入已经存在的引用,只有不同的sequence_nr,因此可能最终在记录集合中的任何地方,但很可能不在结束。
关于我的问题:将非聚集索引作为主键更好或者更好地引入标识列,使其成为聚簇主键并保留引用组合的索引和sequence_nr
?
暂时知道(并且根本无法预见),除了必须确定新sequence_nr
的情况外,无需密集查询此表。
编辑回答问题: Tbh,我不确定生产环境中的超时。我知道在并行运行的进程中添加了新文档。
表:
CREATE TABLE [dbo].[tbl_document] (
[reference] VARCHAR(50) NOT NULL,
[sequence_nr] INT NOT NULL,
[creation_date] DATETIME2 NOT NULL,
[creation_user] NVARCHAR (50) NOT NULL,
[document_data] VARBINARY(MAX) NOT NULL
);
主键:
ALTER TABLE [dbo].[tbl_document]
ADD CONSTRAINT [PK_tbl_document] PRIMARY KEY CLUSTERED ([reference] ASC, [sequence_nr] ASC)
WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, STATISTICS_NORECOMPUTE = OFF);
存储过程:
CREATE PROCEDURE [dbo].[usp_save_document] @reference NVARCHAR (50),
@sequence_nr INT OUTPUT,
@creation_date DATETIME2,
@creation_user NVARCHAR(50),
@document_data VARBINARY(max)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @current_sequence_nr INT
SELECT @current_sequence_nr = max(sequence_nr)
FROM [dbo].[tbl_document]
WHERE [reference] = @reference
IF @current_sequence_nr IS NULL
BEGIN
SELECT @sequence_nr = 1
END
ELSE
BEGIN
SELECT @sequence_nr = @current_sequence_nr + 1
END
INSERT INTO [dbo].[tbl_document]
([reference],
[sequence_nr],
[creation_date],
[creation_user],
[document_data])
VALUES (@reference,
@sequence_nr,
@creation_date,
@creation_user,
@document_data)
END
希望有所帮助。
答案 0 :(得分:2)
我会设置PK
not clustered
,因为:
varchar
时,保持b树平衡,使每个叶子更大。答案 1 :(得分:1)
由于聚簇索引对表的记录进行物理重新排序以匹配索引顺序,因此仅在您希望按该顺序读出多个连续记录时才有用,因为这样可以通过执行顺序读取来读取整个记录磁盘。
如果您只使用索引中存在的数据,那么将其集群化没有任何好处,因为索引本身(已聚集或未聚集)与数据保持独立并按顺序排列。
因此,对于您的特定情况,非聚集索引是正确的方法。插入不需要重新排序数据(只有索引),只需查看索引就可以找到新的sequence_nr
。