Sql 如何判断索引是否包含varchar(max)类型的列?
我正在编写MSSQL索引碎片整理脚本。某些类型的索引可以在线重建,而其他类型的索引则不能 对于聚集索引,很容易看到表是否包含任何LOB列,但对于非聚集索引,我需要明确知道该特定索引是否包含任何LOB列 我过去可以通过查看dm_db_index_physical_stats中的alloc_unit_type_desc来实现这一点,但这不适用于varchar(max)和xml类型的列 这不适用于我的数据库,所以我不想讨论索引是否合适,让我们接受它的存在,并且我希望脚本能够处理这种情况Sql 如何判断索引是否包含varchar(max)类型的列?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我正在编写MSSQL索引碎片整理脚本。某些类型的索引可以在线重建,而其他类型的索引则不能 对于聚集索引,很容易看到表是否包含任何LOB列,但对于非聚集索引,我需要明确知道该特定索引是否包含任何LOB列 我过去可以通过查看dm_db_index_physical_stats中的alloc_unit_type_desc来实现这一点,但这不适用于varchar(max)和xml类型的列 这不适用于我的数据库,所以我不想讨论索引是否合适,让我们接受它的存在,并且我希望脚本能够处理这种情况 有人知道我可以
有人知道我可以编写什么样的SQL来检查这一点吗?假设我在标量变量中有所有相关的对象ID和对象名称。我认为对于“max”列,sys.columns表中的长度或大小feild应该是-1。我面前没有文档,但请告诉我这是否有效。如果您有一个最大长度的char或nvarchar,那么它将在sys.columns表中有一个条目,该字段具有相应的系统类型id,最大长度为-1 因此,如果您想查找所有具有varchar(系统类型id 167)的索引的所有id,您可以执行以下操作:
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
小心点,伙计们。对于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_列查找包含LOB的索引的代码。我在WHERE子句中注释掉了system\u type\u 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,16级,状态2,第1行联机索引操作无法执行
对索引“PK_IndexTest_Has_LOB”执行,因为该索引包含
数据类型text、ntext、image、varchar(max)的“SomeLOB1”列,
nvarchar(max)、varbinary(max)或xml。对于非聚集索引
对于聚集索引,列可以是索引的包含列
可以是表中的任何列。如果列中存在drop_
可能是新索引或旧索引的一部分。必须执行该操作
离线
向Remus Rusanu(系统不允许我发布链接)提示一下
。。。我们可以尝试一些不同的东西。每个索引(集群、非集群或堆)显示为一个分配单元,还将标识行内数据、行外数据和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_列的代码没有这样做
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
您还可以检查DMV-
sys.dm\u db\u index\u physical\u stats
它有一个alloc\u unit\u type\u desc
列,告诉我们索引是否有LOB\u数据
选择S.name作为“Schema”,
T.名称为“表”,
I.名称为“索引”,
DDIPS.avg_碎片(单位:百分比),
DDIPS.page\u计数,
DDIPS.alloc\u装置\u类型\u说明
从sys.dm_db_index_physical_stats(db_ID(),NULL,NULL,NULL,'LIMITED')作为DDIP
T.object\u id=DDIPS.object\u id上的内部联接sys.tables T
T.schema\u id=S.schema\u id上的内部联接sys.schemas
I.object\u id=DDIPS.object\u id上的内部联接sys.index I
和DDIPS.index\u id=I.index\u id
其中DDIPS.database_id=DB_id()
I.name不为空
和DDIPS.alloc\u unit\u type\u desc='LOB\u DATA'
酷豆。我知道它是-1和长度的东西。