Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何判断索引是否包含varchar(max)类型的列?_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 如何判断索引是否包含varchar(max)类型的列?

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类型的列 这不适用于我的数据库,所以我不想讨论索引是否合适,让我们接受它的存在,并且我希望脚本能够处理这种情况 有人知道我可以

我正在编写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和长度的东西。