为数据仓库加载禁用约束和索引的脚本

men*_*osi 2 index data-warehouse sql-server constraint sql-server-2014

我将数据加载到数据仓库中。

目前,为了方便和速度,我有一个脚本,用于在加载数据之前删除外键约束和索引。有一个大窗口,我可以在其中进行加载,因此我不需要担心用户在加载期间访问数据,但我不想影响数据库中其他表中的无关数据。

我在这里其他地方做了一些研究来提出这个脚本,但我想知道是否有一些我可能会忽略的事情可能会使性能欠佳,或者我可能会遗漏一些重要的东西(我不知道 . .. 计算列什么的?)或者我做事顺序错误等等。

任何建议都值得赞赏,以使其健壮和高性能。

禁用约束和索引

编辑:我删除了WHILE评论者帮助我意识到是多余的循环。

Declare @schema varchar(128) = 'dbo';
Declare @sql nvarchar(max) = N'';

-- 1. Indices
-- Select a list of indexes in the schema and generate statements to disable them.
Select @sql = @sql + 'ALTER INDEX ' + QuoteName(idx.name) + ' ON ' + QuoteName(@schema) + '.' + QuoteName(obj.name) + ' DISABLE;' + CHAR(13)
  From sys.indexes As idx
  Join sys.objects As obj On idx.object_id = obj.object_id
  Where ((obj.type = 'U' And idx.type in (2,6)) -- Non-clustered index/columnstore on a table
    Or obj.type = 'V') -- All indexes on indexed views
    And obj.schema_id = (Select schema_id From sys.schemas Where name = @schema)
  Order By obj.name, idx.name;

Execute sp_executesql @sql;


-- 2. Foreign-key constraints
-- Build a list of foreign keys constraints in the schema and generate statements to disable the constraint checking.
Select @sql = @sql + 'ALTER TABLE ' + QuoteName(@schema) + '.' + QuoteName(obj.name) + ' NOCHECK CONSTRAINT ' + QuoteName(fk.name) + ';' + CHAR(13)
  From sys.foreign_keys As fk
  Join sys.objects As obj On fk.parent_object_id = obj.object_id  
  Where obj.schema_id = (Select schema_id From sys.schemas Where name = @schema);

Execute sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

启用约束、重建索引和更新统计信息

Declare @schema nvarchar(128) = 'dbo';
Declare @sql nvarchar(max) = N'';

-- 1. Indices
-- Build a list of tables in the schema and generate statements to enable the indices on them.
Select @sql = @sql + 'ALTER INDEX ' + QuoteName(idx.name) + ' ON ' + QuoteName(@schema) + '.' + QuoteName(obj.name) + ' REBUILD' + iif(idx.type = 6, ' WITH (MAXDOP = 1);', ' WITH (FILLFACTOR = 100);') + CHAR(13)
  From sys.indexes idx
  Join sys.objects obj ON obj.object_id = idx.object_id
  Where ((obj.type = 'U' And idx.type in (2,6)) -- Non-clustered index on a table
    Or obj.type = 'V') -- All indexes on indexed views
    And obj.schema_id = (Select schema_id From sys.schemas Where name = @schema)
    And idx.is_disabled = 1 -- Don't rebuild indexes that are already online
    And idx.is_hypothetical = 0 -- Don't rebuild hypothetical indexes!
  Order By iif(idx.type = 6, 1, 2), obj.name, idx.name;

Execute sp_executesql @sql;


-- 2. Foreign-key constraints
-- Build a list of foreign keys constraints in the schema and generate statements to enable them with checking.
Select @sql = @sql + 'ALTER TABLE ' + QuoteName(@schema) + '.' + QuoteName(obj.name) + ' WITH CHECK CHECK CONSTRAINT ' + QuoteName(fk.name) + ';' + CHAR(13)
  From sys.foreign_keys fk
  Join sys.objects obj ON obj.object_id = fk.parent_object_id
  Where obj.schema_id = (Select schema_id From sys.schemas Where name = @schema)
  Order By obj.name, fk.name;

Execute sp_executesql @sql;


-- 3. Statistics
-- Build a list of tables in the schema and generate statements to update the statistics on them.
Select @sql = @sql + 'UPDATE STATISTICS ' + QuoteName(@schema) + '.' + QuoteName(obj.name) + ' WITH COLUMNS;' + CHAR(13)
  From sys.objects obj
  Where obj.type = 'U' -- User defined
    AND obj.schema_id = (Select schema_id From sys.schemas Where name = @schema)
  Order By obj.name;

Execute sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

Joe*_*ish 5

对于一些你可能没有考虑过的事情:

  1. 如果索引以禁用状态开始,您将在脚本完成后重建它。
  2. 如果索引以页面压缩开始,您将在不压缩的情况下重建它。

对于性能:

  1. 由于没有其他进程正在访问该表,因此您可以使用ONLINE = OFF由于锁定较少而可能会略微提高性能的选项进行重建。
  2. 根据 tempdb 的大小和您的索引,您可以使用该SORT_IN_TEMPDB = ON选项来提高性能。
  3. 您正在更新所有表的统计信息,即使该表尚未修改或更改的行很少。您可以尝试在更新中更加严格,只查看自上次更新统计信息以来修改过的表或根本没有修改过的表。
  4. 看起来您正在单个会话中运行所有这些查询。您是否考虑过在多个会话之间拆分工作?