如何计算其中包含列的非聚集索引的 Num_Key_Cols?

How to calculate the Num_Key_Cols for a Non-Clustered Index with included columns in it?

我正在尝试使用 MSDN website 中提供的信息来估计索引大小。

让我们考虑一个包含三列的 table "Table1"。 下面列出了这些列,

  1. Id int,不为空
  2. 标记为整数,不为空
  3. 提交日期日期,不为空

最初,我在 Id 列上创建了一个聚簇主键,然后计划用 "Id" 创建一个非聚簇索引作为 "index key column" 其中,"Marks""SubmitDate" 列将用作 [=索引中的 26=]"Included Columns".

根据上述计划,我试图在创建非聚集索引键之前估计它的大小。在浏览 MSDN site 时,我有很多困惑需要澄清。估计非聚集索引键大小有四个步骤,第一步,1.2和1.3解释了,如何计算Num_Key_Cols、Fixed_Key_Size、Num_Variable_Key_Cols 和 Max_Var_Key_Size。但是在1.2和1.3,我们要根据Index key的类型来计算,有没有聚簇索引key,有没有包含列;这似乎令人困惑。任何人都可以根据我提供的有关示例 table(表 1)和我想创建的非聚集索引键结构的信息帮助我。

在我的例子中,我包含了列,索引键列已经是主键,并且所有列都不是空字段。如何计算它的索引大小?

提前致谢。

SELECT
OBJECT_NAME(i.OBJECT_ID) AS TableName,
i.name AS IndexName,
i.index_id AS IndexID,
8 * SUM(a.used_pages) AS 'Indexsize(KB)'
FROM sys.indexes AS i
JOIN sys.partitions AS p ON p.OBJECT_ID = i.OBJECT_ID AND p.index_id = i.index_id
JOIN sys.allocation_units AS a ON a.container_id = p.partition_id
GROUP BY i.OBJECT_ID,i.index_id,i.name
ORDER BY OBJECT_NAME(i.OBJECT_ID),i.index_id

Initially, I have created a clustered primary key on Id column and then planned to create a non-clustered index with "Id" as "index key column" where as, "Marks" and "SubmitDate" columns will be used as "Included Columns" in the index.

我不会这样做。通过使 Id 成为 table 的主键(即唯一)和集群键(只有 3 列),在 Id 上添加进一步的 NC 索引几乎没有意义 -聚集索引就足够了。

如果 table 中有大量(页面上的)列,那么可能有理由在 Id 上添加另一个 NC 索引,并在 (Marks, SubmitDate) 上包含列因为 NC 索引密度会更高。但这里显然不是这样。

对 MSDN NC 大小的一些说明 link:

  • 需要在树的所有级别考虑直接索引列。
  • INCLUDE 列仅存在于树的叶节点中
  • Num_Key_Cols = Num_Key_Cols + 1 仅在 Sql 服务器添加 4 byte uniquifier 时才需要,前提是集群键不是唯一的。您已按主键聚类,因此它是唯一的,所以不是 +1。

记得还要对真实数据进行实证测量

并非所有 table 和索引都具有固定的列宽 - 许多具有可变长度的索引列,如 (N)VARCHAR,在这种情况下,table 和索引消耗的实际存储空间高度依赖于此类字段的平均长度。

在这种情况下,我建议创建 table 并用近似数据填充它,然后使用 sp_spaceusedsys.dm_db_index_physical_stats 等工具测量实际数据存储,例如:

select * from sys.dm_db_index_physical_stats (DB_ID(), 
           OBJECT_ID(N'dbo.Table1'), NULL, NULL , 'DETAILED');

(页面大小为 8192)

编辑

只是为了说明,如果您已经准备好了:

CREATE TABLE Table1
(
    Id INT IDENTITY(1,1),
    Marks INT NOT NULL,
    SubmitDate DATE NOT NULL
);

ALTER TABLE Table1 ADD CONSTRAINT PK_Table1 PRIMARY KEY CLUSTERED (Id);

那么这样做也没有意义:

CREATE NONCLUSTERED INDEX IX_Table1 on Table1(Id) INCLUDE (Marks, SubmitDate)

由于聚簇索引已经在 ID 上进行搜索/扫描,性能与 NC 索引一样 - 您只需将存储需求增加一倍。

顺便说一句,还请注意,通常 the clustered index key is included in all non-clustered indexes 是自动的,不需要显式添加到非聚集索引中。