聚集列存储上的非聚集索引存储

Pau*_*ite 19 sql-server database-internals columnstore sql-server-2016

在 SQL Server 中,行存储表上的非唯一非聚集索引在非聚集索引结构的所有级别合并了基础对象的书签(RID 或聚集键)。书签作为非聚集索引键的一部分存储在所有索引级别。

另一方面,如果非聚集索引是unique,则书签仅存在于索引的级别 - 不作为键的一部分(实际上,书签作为一个或多个包含的列存在)。

在 SQL Server 2016 中,可以在面向列的表(具有聚集列存储索引的表)上构建非聚集 b 树索引。

  1. 用于聚集列存储表上的非聚集 b 树索引的“书签”是什么?
  2. 上面描述的唯一和非唯一非聚集索引之间的差异是否仍然适用?

AMt*_*two 18

  1. “书签”是列存储索引原始定位器(根据 Dmitri Korotkevitch 的“Pro SQL Server Internals”)。这是一个 8 字节的值,列存储索引row_group_id位于前 4 字节中,偏移量位于后 4 字节中。

  2. 如果您使用DBCC PAGE查看非聚集索引,则 8 字节列存储索引原始定位符会出现在DBCC PAGE输出的“uniquifier”列中。这表明唯一非聚集索引不需要包含列存储行定位符,而非唯一非聚集索引则需要。

以下代码创建一个按列存储组织的表,该表在同一列上具有唯一且非唯一的 b 树非聚集索引:

CREATE TABLE dbo.Heapish
(
    c1 bigint NOT NULL,
    c2 bigint NOT NULL,
    INDEX CCI_dbo_Heapish CLUSTERED COLUMNSTORE
);
GO
INSERT dbo.Heapish WITH (TABLOCKX)
    (c1, c2)
SELECT TOP (1024 * 1024 * 8)
    c1 = ROW_NUMBER() OVER
        (ORDER BY C1.[object_id], C1.column_id),
    c2 = ROW_NUMBER() OVER
        (ORDER BY C1.[object_id], C1.column_id)
FROM master.sys.columns AS C1
CROSS JOIN master.sys.columns AS C2
ORDER BY
    c1
OPTION (MAXDOP 1);
GO
CREATE UNIQUE NONCLUSTERED INDEX UNIQUE_c2 ON dbo.Heapish (c2) WITH (MAXDOP = 1);
CREATE NONCLUSTERED INDEX NONUNIQUE_c2 ON dbo.Heapish (c2) WITH (MAXDOP = 1);
Run Code Online (Sandbox Code Playgroud)

我们可以使用以下命令查看 b 树不同级别的索引行的大小sys.dm_db_index_physical_stats

SELECT
    DDIPS.index_level,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.min_record_size_in_bytes,
    DDIPS.max_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(),
    OBJECT_ID(N'dbo.Heapish', N'U'),
    INDEXPROPERTY(OBJECT_ID(N'dbo.Heapish', N'U'), N'UNIQUE_c2', 'IndexID'),
    NULL, 'DETAILED'
) AS DDIPS;

SELECT
    DDIPS.index_level,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.min_record_size_in_bytes,
    DDIPS.max_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(),
    OBJECT_ID(N'dbo.Heapish', N'U'),
    INDEXPROPERTY(OBJECT_ID(N'dbo.Heapish', N'U'), N'NONUNIQUE_c2', 'IndexID'),
    NULL, 'DETAILED'
) AS DDIPS;
Run Code Online (Sandbox Code Playgroud)

输出是:

唯一索引

非异常指数

两种结构在叶级别具有相同的行大小,但由于 8 字节的列存储定位器,非唯一非聚集索引比非叶级别的唯一非聚集索引大 12 个字节,加上第一个变量的 4 个字节开销- 一行中的长度列(唯一符是可变长度)。