Ser*_*uei 8 sql sql-server foreign-keys check-constraints sql-server-2012
如果我们有一个巨大的事实表并且想要添加一个新维度,我们可以这样做:
BEGIN TRANSACTION
ALTER TABLE [GiantFactTable]
ADD NewDimValueId INT NOT NULL
CONSTRAINT [temp_DF_NewDimValueId] DEFAULT (-1)
WITH VALUES -- table is not actually rebuilt!
ALTER TABLE [GiantFactTable]
WITH NOCHECK
ADD CONSTRAINT [FK_GiantFactTable_NewDimValue]
FOREIGN KEY ([NewDimValueId])
REFERENCES [NewDimValue] ([Id])
-- drop the default constraint, new INSERTs will specify a value for NewDimValueId column
ALTER TABLE [GiantFactTable]
DROP CONSTRAINT [temp_DF_NewDimValueId]
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
注意:以上所有内容仅操纵表元数据,无论表大小如何都应该快速.然后我们可以运行一个工作来回填GiantFactTable.NewDimValueId小事务,这样就不会违反FK.(此时任何INSERT/UPDATE - 例如回填操作 - 都由FK验证,因为它已启用,但不是"可信")
在回填之后,我们知道数据是一致的,我的问题是SQL引擎如何变得开明?不使表离线.
此命令将使FK受信任,但它需要架构修改(Sch-M)锁定并且可能需要数小时(几天?)使表离线:
ALTER TABLE [GiantFactTable]
WITH CHECK CHECK CONSTRAINT [FK_GiantFactTable_NewDimValue]
Run Code Online (Sandbox Code Playgroud)
关于工作负载:表有几百个分区(固定数量),数据一次附加到一个分区(以循环方式),从不删除.还有一个恒定的读取工作负载,它使用群集密钥一次从一个分区获取(相对较小的)行范围.一次检查一个分区,使其脱机,是可以接受的.但我找不到任何语法来做到这一点.还有其他想法吗?
我想到了一些想法,但它们并不漂亮:
alter table以检查约束并让它按照需要的时间运行上述的一种变体是在步骤 3 中将相关分区切换到新表。这应该比复制数据更快,但我认为您必须在检查约束后将数据复制(而不仅仅是切换)回来。
我不知道这是否有效,但您可以尝试在外键列上创建非聚集索引。还要确保外键引用的表上的相关唯一键有索引。该alter table命令可能能够使用它们来加快检查速度(至少与全表扫描相比可以最大限度地减少 IO)。当然,可以在线创建索引以避免任何中断。