在线重建索引而不会对其他请求造成风险

Hug*_*une 6 sql-server sql-server-2012 index-maintenance

我们有一个 SQL Server 2012 企业版数据库,它的索引碎片非常快。

我们使用维护计划每天重新组织这些索引,并每周重建它们。重建在线进行并使用 tempdb(企业版 SQL Server 功能)。

然而,在重建的 2 分钟内,与数据库的其他连接受到影响。我们会遇到几次超时或死锁。有时,重建本身也会因死锁而失败。

重建失败没问题,我们可以再试一次。但是其他连接超时甚至需要很长时间是非常麻烦的。

有没有办法以较低的优先级运行重建,或者如果当前的处理资源不足以进行在线重建,则自动失败?

此数据库没有停机时间窗口,因此我们无法离线重建索引。有什么方法可以在线重建索引而不会对其他请求造成重大干扰?

Han*_*non 6

有几个选项可以帮助减少您看到的问题:

/* set the LOCK_TIMEOUT value to the maximum number of milliseconds 
   you want to wait for the ALTER INDEX REBUILD to start
*/
SET LOCK_TIMEOUT 100;

/* this tells SQL Server our ALTER INDEX REBUILD statement should
   be the deadlock victim
*/
SET DEADLOCK_PRIORITY LOW;

/* Rebuild the index */
ALTER INDEX MyIndex 
ON MySchema.MyTable 
REBUILD WITH (
    ONLINE = ON
    , ALLOW_ROW_LOCKS = ON
    , ALLOW_PAGE_LOCKS = ON
    , MAXDOP = 1
    );
Run Code Online (Sandbox Code Playgroud)

我知道您有 SQL Server 2012,但是对于 SQL Server 2014+,您可以使用该WAIT_AT_LOW_PRIORITY选项告诉 SQL Server 允许其他会话继续,而在线索引构建操作正在等待获取其架构修改锁。

ALTER INDEX MyIndex 
ON MySchema.MyTable 
REBUILD WITH (
    ONLINE = ON (WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = SELF))
    , ALLOW_ROW_LOCKS = ON
    , ALLOW_PAGE_LOCKS = ON
    , MAXDOP = 1
    );
Run Code Online (Sandbox Code Playgroud)

来自 MSDN SQL Server 联机丛书:

为了执行联机索引重建的 DDL 语句,必须完成在特定表上运行的所有活动阻塞事务。当联机索引重建执行时,它会阻止所有准备好在此表上开始执行的新事务。虽然在线索引重建的锁持续时间很短,但等待给定表上所有打开的事务完成并阻塞新事务的启动,可能会显着影响吞吐量,导致工作负载变慢或超时,并显着限制访问基础表。WAIT_AT_LOW_PRIORITY 选项允许 DBA 管理联机索引重建所需的 S-lock 和 Sch-M 锁,并允许他们选择 3 个选项之一。在所有 3 种情况下,