使用分区切换高效传输数据

将数据分区可以快速、有效地管理和访问数据的子集,同时又能维护整个数据集合的完整性。可以使用 Transact-SQL ALTER TABLE...SWITCH 语句通过以下方式快速高效地转移数据子集:

  • 将表作为分区分配到现有的已分区表。

  • 将分区从一个已分区表切换到另一个已分区表。

  • 重新分配一个分区以形成单个表。

如需了解有关分区切换概念的信息和查看实现分区切换的示例代码,请参阅 Readme_SlidingWindow

切换分区的常规要求

在转移分区时,数据在物理上并未移动;只不过是有关数据位置的元数据有了改动。必须满足下面几项一般性的要求才能切换分区:

  • 在 SWITCH 操作之前两个表必须都存在。在执行切换操作之前,从中移出该分区的表(源表)以及接收该分区的表(目标表)都必须存在于数据库中。

  • 接收分区必须存在并且必须是空的。无论是将表作为分区添加到现有的已分区表,还是将分区从一个已分区表移动到另一个已分区表,接收新分区的分区都必须存在并且必须为空分区。

  • **不分区的接收表必须存在且必须是空的。**如果要重新分配一个分区以形成一个不分区的表,则接收新分区的表必须存在并且必须为空的不分区表。

  • **各分区必须依据同一列。**如果要将分区从一个已分区表切换到另一个已分区表,则这两个表必须依据同一列进行分区。

  • **源表和目标表必须共享同一个文件组。**ALTER TABLE...SWITCH 语句的源表和目标表必须位于同一文件组,并且其大值列也必须存储在同一文件组中。所有对应的索引、索引分区或索引视图分区也必须位于同一文件组中。不过,该文件组可以与对应表或其他对应索引的文件组不同。

有关定义了索引视图时的分区切换的信息,请参阅定义了索引视图时的分区切换

表和索引的结构要求

除了上述一般性要求之外,源表和目标表必须具有相同的结构。结构要求如下:

  • 源表和目标表必须具有相同的列结构和顺序。这两个表必须具有相同的列,并且列的名称、数据类型、长度、排序规则、精度、小数位数、为空性和 PRIMARY KEY 约束(如果有)都相同,这两个表还必须具有相同的 ANSI_NULLS 和 QUOTED IDENTIFIER 设置。另外,必须以相同的顺序定义列。不考虑 IDENTITY 属性。

    注意事项注意

    分区切换可在目标表的 IDENTITY 列中引入重复的值,并可导致源表的 IDENTITY 列值不连贯。使用 DBCC CHECKIDENT 检查表的标识值,并根据需要更改这些值。

  • 分区依据列的为空性必须匹配。源表和目标表必须都为 NULL 或都为 NOT NULL。如果其中一个表没有进行分区,则与另一个表的分区依据列对应的列的为空性必须与已分区表的此列匹配。

    重要说明重要提示

    建议您对已分区表的分区依据列指定 NOT NULL。还建议您对作为 ALTER TABLE...SWITCH 操作的源或目标的不分区表指定 NOT NULL。当已分区列为 NOT NULL 时,则不会强制分区依据列的任何 CHECK 约束检查是否有 NULL 值。NULL 值通常置于已分区表最左侧的分区中。在切换最左侧分区以外的任何分区时以及在将 ANSI_NULLS 数据库选项设置为 ON 时,如果源表和目标表不存在 NOT NULL 约束,这可能会干扰同时对分区依据列定义的任何 CHECK 约束。

  • 计算列必须具有相同的语法。如果其对应分区键是计算列,则定义其计算列的表达式的语法是相同的,而且计算列都是永久的。

  • **ROWGUID 属性必须相同。**任何定义有 ROWGUID 属性的列必须对应于另一个表中同样定义有 ROWGUID 属性的列。

  • **XML 列必须具有相同的架构。**必须将所有 xml 列按类型归入同一个 XML 架构集合。

  • **所有 text、ntext 或 image 列的行内设置都必须相同。**有关此设置的详细信息,请参阅行内数据

  • 表必须具有相同的聚集索引。源表和目标表必须具有相同的聚集索引,并且在切换分区之前不能禁用这些索引。

  • **必须定义非聚集索引并且这些索引必须相同。**如果对目标表定义了任何非聚集索引,则对源表也需要定义这些非聚集索引,并且这两个表的非聚集索引在每个索引键列的唯一性、子键和排序方向(ASC 或 DESC)方面的设计都应相同。禁用的非聚集索引没有此要求。

约束要求

若要移动分区,还必须满足下面的其他约束要求:

  • **源和目标的 CHECK 约束必须完全匹配或前者的约束适用于后者的约束。**如果对目标表定义了任何 CHECK 约束,则对源表也必须定义这些约束,并且,源表的这些约束需与目标表的相应约束完全匹配或适用于目标表的 CHECK 约束(例如,作为其子集)。

  • **对 int 列的约束必须相同或存在子集关系。**源表的 int 列的 CHECK 约束必须与目标表的 int 列的约束匹配或作为其子集存在。例如,如果目标表的 int 列 Column1 具有指定 Column1 < 100 的约束,则源表对应的列 Column1 必须具有同一约束或具有针对目标表中值的约束的子集,例如源表的约束可以为 Column1 < 90。指定多个列的 CHECK 约束必须使用相同的语法来定义。

  • **不分区表必须与目标分区具有相同的约束。**如果要将一个无分区表作为一个分区添加到一个现有已分区表,则必须对对应于目标表分区键的源表的列定义一个约束。这将确保值的范围在目标分区的边界值内。

  • **源分区的边界值必须在目标分区的边界内。**如果要将一个已分区表的某个分区切换到另一个已分区表,则源分区的边界值必须在目标分区的边界值内。如果边界值不适合,则必须对源表的分区键定义一个约束以确保表中的所有数据在目标分区的边界值内。

    注意事项注意

    在约束定义中避免数据类型转换。对作为分区切换的源表定义的且包含隐式或显式数据类型转换的约束可能会导致 ALTER TABLE...SWITCH 失败。

  • **源表和目标表必须具有相同的 FOREIGN KEY 约束。**如果目标表具有任何 FOREIGN KEY 约束,则对源表的相应列必须定义了相同的外键,并且这些外键引用的主键必须与目标表中的外键引用的主键相同。源表的外键不能标记为 is_not_trusted(可在 sys.foreign_keys 目录视图中查看),除非目标表的相应外键也标记为 is_not_trusted。有关此设置的详细信息,请参阅禁用索引准则。SQL Server 将对目标表的外键定义的所有 CASCADE 规则都应用到新移动的分区。

移动分区的额外要求

若要移动分区,还必须满足以下额外要求:

  • **索引必须与表分区对齐。**源表的所有索引必须与源表对齐,目标表的所有索引必须与目标表对齐。源表和目标表可以都分区,都不分区,或只有其中一个表分区。有关索引对齐的详细信息,请参阅已分区索引的特殊指导原则

  • **其他约束和要求适用于带索引视图的源表。**如果 ALTER TABLE … SWITCH 语句中的目标表定义了索引视图,请参阅定义了索引视图时的分区切换以了解相关约束和示例。

  • **允许没有全文索引。**源表或目标表都可以没有全文索引。

  • **允许目标表没有 XML 索引。**在目标表可以没有 XML 索引。

  • **在源表具有主键的情况下可以不定义主键/外键关系。**在源表包含主键的情况下源表和目标表之间可以没有活动的主键/外键关系。

  • **在目标表具有外键的情况下可以不定义主键/外键关系。**在目标表包含外键的情况下源表和目标表之间可以没有活动的主键/外键关系。

  • **另一个表的任何外键都不能引用源表。**另一个表中的外键不能引用源表。

  • **不允许对源表或目标表使用规则。**不能对源表或目标表定义规则。可以对源表和目标表使用 CHECK 约束。

    注意注意

    规则是一个向后兼容的功能。优先考虑使用 CHECK 约束来实现。有关 CHECK 约束的限制,请参阅本主题前面的约束要求。

  • **不得复制源表和目标表。**源表和目标表都不能成为复制源。

  • **在分区切换之前必须拥有所需的数据库权限。**由于切换分区时使用的是 ALTER TABLE 语句,因此您必须拥有与 ALTER TABLE 语句关联的所需数据库权限。权限集在源表和目标表间不必相同。

  • **移动分区时触发器必须处于非活动状态。**移动表分区时不能激发 INSERT、UPDATE 或 DELETE 触发器或者级联操作,并且源表或目标表不需要具有在定义方面相似的触发器即可移动分区。

    注意注意

    在 ALTER TABLE…SWITCH 操作期间,源表和目标表都将获取一个架构修改锁,以确保在更改期间其他任何连接都无法引用这些表。有关锁的详细信息,请参阅锁模式

移动表分区