已分区索引的特殊指导原则

尽管可以从已分区索引的基表中单独实现已分区索引,但通常的做法是先设计一个已分区表,然后为该表创建索引。执行此操作时,SQL Server 将使用与该表相同的分区方案和分区依据列自动对索引进行分区。因此,索引的分区方式实质上与表的分区方式相同。这将使索引与表“对齐”。

如果在创建时指定了不同的分区方案或单独的文件组来存储索引,则 SQL Server 不会将索引与表对齐。

如果您预计将通过使用更多分区来扩展索引,或者将会涉及到频繁的分区切换,那么将索引与已分区表对齐将非常重要。有关详细信息,请参阅设计分区以管理数据子集。如果表与其索引对齐,SQL Server 则可以快速高效地切换分区,同时又能维护表及其索引的分区结构。

注意注意

索引要与其基表对齐,并不需要与基表参与相同的命名分区函数。但是,索引和基表的分区函数在实质上必须相同,即:1) 分区函数的参数具有相同的数据类型;2) 分区函数定义了相同数目的分区;3) 分区函数为分区定义了相同的边界值。

数据库引擎优化顾问的**“优化选项”选项卡提供了“对齐分区”设置,用于指定新的建议索引与其基表对齐。“保留对齐分区”**设置可用于相同的目的,还可用于删除未对齐的现有索引。有关详细信息,请参阅数据库引擎优化顾问(“优化选项”选项卡)。通常,数据库引擎优化顾问可用于提供建议索引以优化性能,而建议索引可以既包括对齐索引又包括未对齐索引。有关详细信息,请参阅数据库引擎优化顾问概述

在下列情况下,独立于基表而单独设计已分区索引(不对齐)很有用:

  • 基表未分区。

  • 索引键是唯一的,不包含表的分区依据列。

  • 您希望基表与使用不同联接列的多个表一起参与组合联接。

注意注意

若要启用分区切换,表的所有索引都必须对齐。

创建已分区索引时,请考虑下列各节中的信息。

对唯一索引进行分区

对唯一索引(聚集或非聚集)进行分区时,必须从唯一索引键使用的分区依据列中选择分区依据列。

注意注意

此限制将使 SQL Server 只调查单个分区,以确保表中不存在重复的新键值。

如果分区依据列不可能包含在唯一键中,则必须使用 DML 触发器,而不是强制实现唯一性。

对聚集索引进行分区

对聚集索引进行分区时,聚集键必须包含分区依据列。对非唯一的聚集索引进行分区时,如果未在聚集键中明确指定分区依据列,默认情况下 SQL Server 将在聚集索引键列表中添加分区依据列。如果聚集索引是唯一的,则必须明确指定聚集索引键包含分区依据列。

对非聚集索引进行分区

对唯一的非聚集索引进行分区时,索引键必须包含分区依据列。对非唯一的非聚集索引进行分区时,默认情况下 SQL Server 将分区依据列添加为索引的非键(包含性)列,以确保索引与基表对齐。如果索引中已经存在分区依据列,SQL Server 将不会向索引中添加分区依据列。

内存限制和已分区索引

内存限制可能会影响 SQL Server 生成已分区索引的性能或能力。如果表中已应用聚集索引,当索引未与其基表或聚集索引对齐时更是如此。

当 SQL Server 执行排序以生成已分区索引时,它首先为每个分区生成一个排序表。然后在每个分区各自的文件组中生成排序表,或者在 tempdb 中生成排序表(如果指定了 SORT_IN_TEMPDB 索引选项)。

每个排序表都需要一个最小内存量才能生成。在生成与其基表对齐的已分区索引时,将一次生成一个排序表,因此使用的内存较少。但是,在生成非对齐的已分区索引时,将同时生成排序表。

因此,必须有足够的内存来处理这些并发的排序。分区数越多,所需的内存越多。每个分区的每个排序表的最小大小为 40 页,每页 8 KB。例如,具有 100 个分区的非对齐已分区索引需要足够的内存才能同时连续地对 4,000 (40 * 100) 页进行排序。如果有这么多的可用内存,生成操作将成功,但性能可能会降低。如果没有这么多可用内存,生成操作将失败。而具有 100 个分区的对齐已分区索引只需要具有对 40 页进行排序的内存就足够了,因为不会同时执行排序。

无论是对齐索引还是非对齐索引,如果 SQL Server 对多处理器计算机上的生成操作应用了并行度,需要的内存可能会更多。这是因为并行度越高,需要的内存就越多。例如,如果 SQL Server 将并行度设置为 4,那么具有 100 个分区的非对齐已分区索引将需要使四个处理器同时分别对 4,000 页(即,共 16,000 页)进行排序的足够内存。如果已分区索引是对齐的,需要的内存将减少,只要够四个处理器分别对 40 页(共 160 页,即 4 * 40)进行排序就行了。您可以使用 MAXDOP 索引选项手动降低并行度。有关详细信息,请参阅配置并行索引操作

有关生成索引时 SQL Server 如何执行排序操作的详细信息,请参阅 tempdb 和索引创建