假设表有 name 和 id 列。
ID是唯一的非聚集索引。所以this指向堆表。
如果我将Name设置为聚集索引(非唯一),那么ID非聚集索引将指向什么?
我知道它不会指向堆,因为该表现在是聚集索引。
通常,非聚集索引指向聚集键,但在上述情况下,聚集键不是唯一的。那么ID(非聚集索引)指向什么呢?
非聚集索引 (NC) 指向聚集索引 (CL) 键,即使 CL 索引不唯一。
当集群键中遇到重复项时,SQL Server 会添加唯一符。我认为经常被忽视的是,这个唯一符只是为重复项添加的。
如果您用完唯一符(集群键超过大约 40 亿个重复项),您会收到可怕的错误 666,并且您可能应该重新考虑集群键的选择:
The maximum system-generated unique value for a duplicate group was exceeded for index with partition ID %I64d. Dropping and re-creating the index may resolve this; otherwise, use another clustering key.
Run Code Online (Sandbox Code Playgroud)
下面的示例显示您无需为值的第一个实例支付 4 字节的惩罚:
--Table to play with
DROP TABLE IF EXISTS t
CREATE TABLE t(c1 char(3), c2 char(3))
CREATE CLUSTERED INDEX x ON t(c1)
GO
--Table to hold output from DBCC PAGE
DROP TABLE IF EXISTS dbccpage
CREATE TABLE dbccpage(ParentObject_ varchar(200), Object_ varchar(200), Field_ varchar(200), Value_ varchar(1000))
GO
INSERT INTO t VALUES('aaa', 'AAA'), ('aaa', 'A2A'), ('aaa', 'A3A'), ('bbb', 'BBB')
--This doesn't show enough details regarding uniqueifier
SELECT *
FROM t
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%) AS f
CROSS APPLY sys.dm_db_page_info(DB_ID(), f.file_id, f.page_id, 'Detailed')
--DBCC PAGE to the rescue
--Get output to calling app
DBCC TRACEON(3604)
GO
DECLARE
@dbid int = Db_ID()
,@fileno int
,@pageno int
,@sql varchar(1000)
SELECT TOP(1) @fileno = f.file_id, @pageno = page_id
FROM t
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%) AS f
SET @sql = CONCAT('DBCC PAGE(', @dbid, ', ', @fileno, ', ', CAST(@pageno AS varchar(10)), ', 1) WITH TABLERESULTS' )
PRINT @sql
INSERT INTO dbccpage
EXEC(@sql)
--Output:
SELECT Field_, Value_
FROM dbccpage
WHERE ParentObject_ LIKE 'DATA:' OR ParentObject_ like 'Slot%'
Run Code Online (Sandbox Code Playgroud)