有人问了我一个最有意思的问题:“你能禁用聚集索引么?

对这个问题,我先是吓了一跳,因为我从未想过禁用聚集索引,因为聚集索引代表表数据,对这个最有趣问题,我立即答道:“我认为可以,但是...

好吧,我们现在来讨论下“但是”。你禁用聚集索引,但我真的不知道SQL Server会如何反应,因此我们来试验下。

(以下代码运行在AdventureWorks2008R2数据库)

 -- Let's disable a Clustered Index
ALTER INDEX PK_Person_BusinessEntityID ON Person.Person DISABLE
GO

哈!语句还是可以正常执行的!但是你收到很多不同的外键约束也被禁用的警告。

在SQL Server里禁用聚集索引——真的好么?-LMLPHP

好,我们已经禁用了表的聚集索引,但我们也有效的禁用了表本身。我们对禁用的聚集索引运行一个简单的SELECT语句。

 -- Let's run a SELECT statement against the disabled Clustered Index
SELECT * FROM Person.Person
GO

这下玩完了!!!查询处理器无法生成计划,我们弄坏了我们的SQL语句。

在SQL Server里禁用聚集索引——真的好么?-LMLPHP

当你开始考虑它的时候,很能想到这是有道理的:我们禁用了聚集索引,也禁用了表本身!但这不应该真的有关系,因为表上有非聚集索引,也可以作为我们获取数据的路径。

我们再想下。我们是否可以通过非聚集索引来访问表数据?理论上是可以的,只要选择的非聚集索引是覆盖非聚集索引。如果你通过从聚集索引的书签查找来请求一些其它列,你还是会有大问题,因为聚集索引已经禁用。因此我们来通过查询sys.index来看下非聚集索引的状态:

 SELECT object_id , name ,index_id ,type ,type_desc , is_disabled  FROM sys.indexes WHERE object_id=OBJECT_ID('Person.Person')

在SQL Server里禁用聚集索引——真的好么?-LMLPHP

哇!我们所有的的非聚集索引也被禁用了!现在根本没有方法访问我们的数据了。这是完全有道理的,因为不然的话会引入需要书签查找的巨大问题。现在我们通过禁用聚集索引已经完全把表下线了!

怎么恢复表在线呢?简单:我们需要重建我们的聚集索引:

 -- Let's rebuild the Clustered Index
ALTER INDEX PK_Person_BusinessEntityID ON Person.Person REBUILD
GO

很简单,是不是?但当我们再次查询sys.index时,我们会看到我们的非聚集索引“还是禁用的”

在SQL Server里禁用聚集索引——真的好么?-LMLPHP

因此我们“也要”重建我们的非聚集索引,让它们恢复在线。

教训:绝不禁用表的聚集索引!

感谢关注!

原文链接:

http://www.sqlpassion.at/archive/2016/04/11/disabling-clustered-indexes-in-sql-server-a-really-good-idea/

05-06 16:17