繁体   English   中英

SQL Server更新索引设计

[英]SQL Server Update Indexing Design

我有一张表,IDMAP和DML:

CREATE TABLE tempdb2.dbo.idmaptemp (
    OldId varchar(20),
    CV_ModStamp datetimeoffset,
    NewId varchar(20),
    RestoreComplete bit,
    RestoreErrorMessage varchar(1000),
    OperationType varchar(20)
)

按照定义,它已经包含约(100万)个预定义的行集。 恢复操作完成后,我必须更新表上的NewId,RestoreComplete,RestoreErrorMessage。 该语句是:

update tempdb2.dbo.IdMaptemp set NewId = 'xxx', RestoreComplete = 'false', RestoreErrorMessage = 'error' where OldId = 'ABC';

Java应用程序在内存上具有大约一百万个值,并且必须使用上述语句更新这些值。 数据库设置为自动提交,并且随批次(批次大小500)而变化。

我在使用OldId索引字段上尝试了两个选项:

  1. 聚集索引-执行计划列为聚集索引更新(100%成本)。 这是因为叶子是要更新的行,这将触发索引更新。 我在这里吗?

  2. 非聚集索引-执行计划列出为更新(75%)和搜寻(25%)。

在数据库表上进行批量更新是否还能实现其他速度提升? 无法清除并重新插入该表,因为还有其他不受更新影响的行。 每批500行的样本的聚集索引大约需要7个小时才能更新。

我应该选择非聚集索引选项吗?

更改大表的聚集索引是一项昂贵的提议。 表的聚集索引是为整个表而不是为行的子集定义的。

如果您将oldid保留为聚集索引,而只是想提高批处理性能,请考虑允许db参与批处理过程,而不是应用程序/ java层。 要求数据库一次更新1行,数百万行是一项昂贵的提议。 用临时批处理填充临时表,然后让SQL一次更新整个批处理可能是提高性能的一种好方法。

insert #temptable (OldId,NewId)
...

Update
set T1.NewId = T2.NewId
T1
from
T1 join #tempTable T2
on T1.OldId = T2.OldId

如果可以计算新的ID,请考虑另一种批处理策略。

update tempdb2.dbo.IdMaptemp top 1000 set NewId = 'xxx', RestoreComplete = 'false', 
    RestoreErrorMessage = 'error' where NewId is null;

如果您真的想使用NewId作为聚簇索引创建新表,请根据需要创建新表

insert into NewTable()
select top 10000 *
from OldTable O
left join NewTable N
on O.OldId = N.OldId
where N.OldId is null

完成后,放下旧表。

注意:您的ID是否需要为20个字节? 通常,聚簇索引为int-4个字节或bigint-8个字节。

如果这是一次性的事情,那么更改大型持久性表上的聚集索引将是值得的。 如果oldid始终处于获取newid值的过程中,而这仅是您拥有的工作流程,那么我就不会费心更改持久表的聚集索引。 只需将oldid保留为聚集索引即可。 NewId听起来像是代理键。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM