当您要更改现有的非聚集索引时,SQL Server提供了各种各样的选项。最常用的方法之一是DROP EXISTING;在这篇文章中,你将了解所有关于这个选项。该选项在重新创建一个新索引后自动删除该索引,而不会显式地删除该索引。让我们花点时间来理解这种选择的行为。
DROP EXSITING=ON
这是我喜欢的方法,只有在它用新的定义创建和构建索引之后才会删除当前的索引。这样做的缺点是,如果索引不存在,就会出现错误,必须在没有该选项的情况下创建该索引,或者将其设置为OFF。然而,使用这个索引更重要的好处在于性能。在使用新的定义重新构建索引之前,活动查询仍将使用该索引。
CREATE NONCLUSTERED INDEX [dcacIDX_ServiceType] ON [dbo].[Accounts]
(
[ServiceType] ASC
)
INCLUDE([AccountId]) WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = ON, ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
如果index不存在,您将得到一个7999错误。
Msg 7999, Level 16, State 9, Line 1
Could not find any index named 'dcacIDX_ServiceType' for table 'dbo.Accounts'.
在docs.microsoft.com上有一些例外需要记住
使用DROP_EXISTING,您可以更改,
- 群集行存储索引的非群集行存储索引
使用DROP_EXISTING,您不能更改,
- 指向非聚集行存储索引的聚集行存储索引
- 指向任何类型的rowstore索引的聚集columnstore索引
DROP and CREATE
如果索引不存在,这个选项是一个更简洁的错误。但是,在使用它时,尤其是当它是一个大表时,我要提醒你。使用这个选项在创建新索引之前删除索引,使您的系统没有先前的索引定义。在系统等待创建新索引时,这可能会产生巨大的性能问题。我亲身体会到这一点,几年前,我在试图解决性能问题的某一天与一位客户这样做过。我创建了一个更糟糕的问题,而等待新的问题被创建。使用新定义创建新索引花了45分钟,这导致CPU峰值达到100%,而活动查询试图通过。不幸的是,这反过来又减缓了新指数的产生。
DROP INDEX IF EXISTS [dcacIDX_ServiceType] ON [dbo].[Accounts]
GO
CREATE NONCLUSTERED INDEX [dcacIDX_ServiceType] ON [dbo].[Accounts]
(
[ServiceType] ASC
)
INCLUDE([AccountId] WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
现在我还应该注意到,当您必须修改聚集索引时,drop_existiting方法也更快。每个非聚集索引都使用所谓的聚集键引用聚集索引,实质上是指向聚集索引中的行的指针。当一个聚集索引被删除并重新创建时,SQL Server必须重建该表上的非聚集索引。实际上,通过在删除时重新构建它们,以及在创建聚集索引时重新构建它们,可以完成两次。使用DROP_EXISTING=ON可以防止你重建所有这些索引,因为它们的键将保持不变,从而使它明显更快。