小心,伙计们。就 LOB 而言,聚簇索引是另一种动物。让我们做一个测试,看看我的意思。
首先,让我们设置一个测试表。此测试不需要数据,但我们确实有一个聚集索引 (IndexID=1) 作为 PK。我们还有一个非聚集索引 (IndexID=2),它不包含作为 INCLUDE 的 LOB 列,我们还有一个包含作为 INCLUDE 的 LOB 列的非聚集索引。这是测试设置代码...
--========================================================================
-- Test Setup
--========================================================================
--===== If the test table already exists,
-- drop it to make reruns in SSMS easier.
IF OBJECT_ID('dbo.IndexTest','U') IS NOT NULL
DROP TABLE dbo.IndexTest
;
GO
--===== Create the test table
CREATE TABLE dbo.IndexTest
(
SomeID INT IDENTITY(1,1)
,SomeInt INT
,SomeLOB1 VARCHAR(MAX)
,CONSTRAINT PK_IndexTest_Has_LOB
PRIMARY KEY CLUSTERED (SomeID)
)
;
--===== Add an index that has no INCLUDE of a LOB
CREATE INDEX IX_Has_No_LOB
ON dbo.IndexTest (SomeInt)
;
--===== Add an index that has INCLUDEs a LOB
CREATE INDEX IX_Includes_A_LOB
ON dbo.IndexTest (SomeInt) INCLUDE (SomeLOB1)
;
现在,让我们尝试使用 sys.index_columns 查找包含 LOB 的索引的代码。我已经注释掉了 WHERE 子句中的 system_type_id 以将其打开一点......
--========================================================================
-- Test for LOBs using sys.index_columns.
--========================================================================
select distinct
si.*
from
sys.indexes as si
inner join sys.index_columns as ic on
ic.object_id = si.object_id and
ic.index_id = si.index_id
inner join sys.columns as sc on
sc.object_id = ic.object_id and
sc.column_id = ic.column_id
where
--sc.system_type_id = 167 and
sc.max_length = -1
;
这是上面运行的输出...
object_id name index_id type type_desc ...
----------- ----------------- ----------- ---- ------------ ...
163204448 IX_Includes_A_LOB 3 2 NONCLUSTERED ...
它无法判断聚集索引包含 LOB,因为 LOB 不是索引列之一。尝试重建此聚集索引将导致失败。
ALTER INDEX PK_IndexTest_Has_LOB
ON dbo.IndexTest REBUILD WITH (ONLINE = ON)
;
Msg 2725, Level 16, State 2, Line 1 无法进行联机索引操作
为索引“PK_IndexTest_Has_LOB”执行,因为该索引包含
数据类型为 text、ntext、image、varchar(max) 的列“SomeLOB1”,
nvarchar(max)、varbinary(max) 或 xml。对于非聚集索引
列可以是索引的包含列,对于聚集索引它
可以是表格的任何列。在 drop_existing 列的情况下
可能是新索引或旧索引的一部分。必须执行该操作
离线。
向 Remus Rusanu 致敬(系统不允许我发布链接)...
...我们可以尝试一些不同的东西。每个索引(集群、非集群或 HEAP)都显示为一个分配单元,并且还将标识行内数据、行外数据和 LOB。下面的代码查找所有与它们关联的 LOB 的索引......甚至是聚集索引。
--===== Find all indexes that contain any type of LOB
SELECT SchemaName = OBJECT_SCHEMA_NAME(p.object_id)
,ObjectName = OBJECT_NAME(p.object_id)
,IndexName = si.name
,p.object_id
,p.index_id
,au.type_desc
FROM sys.system_internals_allocation_units au --Has allocation type
JOIN sys.system_internals_partitions p --Has an Index_ID
ON au.container_id = p.partition_id
JOIN sys.indexes si --For the name of the index
ON si.object_id = p.object_id
AND si.index_id = p.index_id
WHERE p.object_id = OBJECT_ID('IndexTest')
AND au.type_desc = 'LOB_DATA'
;
这会为此特定测试产生以下输出。请注意,它确实通过 object_id 和 index_id 获取了聚集索引,而基于 sys.index_columns 的代码没有。
SchemaName ObjectName IndexName object_id index_id type_desc
---------- ---------- -------------------- --------- -------- ---------
dbo IndexTest PK_IndexTest_Has_LOB 163204448 1 LOB_DATA
dbo IndexTest IX_Includes_A_LOB 163204448 3 LOB_DATA