SQL Server 重建索引 Rebuild Index

本文介绍如何通过重建索引来减少SQL Server中的数据碎片,并提高其性能。包括如何使用不同的工具和自定义代码来更新索引,以及如何设置fillfactor参数以避免过度分页。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重建索引是为了减少数据碎片。数据碎片会导致SQL Server进行不必要的数据读,降低SQL Server的性能。重建索引也会同时更新列统计,而如果查询所使用的列缺少或遗漏统计信息,这可能导致SQL Server内部的优化器选择比预期效率低的查询计划。

 

如果您重建了某张表上的聚集索引,该表上的非聚集索引也同时会被更新。

 

 

要更新索引,您可以使用Maintenance Wizard(相关内容您可以参考http://msdn.microsoft.com/en-us/library/ms180074.aspx),或在SQL Server代理(Agent)中运行如下的自定义代码来更新某个数据库中所有表上的索引:

USE DatabaseName --Enter the name of the database you want to reindex

 

DECLARE @TableName varchar(255)

 

DECLARE TableCursor CURSOR FOR

SELECT table_name FROM information_schema.tables

WHERE table_type = 'base table'

 

OPEN TableCursor

 

FETCH NEXT FROM TableCursor INTO @TableName

WHILE @@FETCH_STATUS = 0

BEGIN

DBCC DBREINDEX(@TableName,' ',90)

FETCH NEXT FROM TableCursor INTO @TableName

END

 

CLOSE TableCursor

 

DEALLOCATE TableCursor

 

您可以根据您的需求修改DBREINDEX的参数。

需要注意的是,重建非聚集索引时该表会暂时加上共享锁,对用户不可进行SELECT以外的操作;重建聚集索引时该表会暂时加上排外锁,不允许任何用户访问。因此需要制定好计划来预防可能的访问问题。

 

REBUILD有一个fill factor参数,如果fill factor设置为100%,这意味着每一个索引页都是完全满的,如果fill factor设置为50%意味着每个索引页都是半满的。对于fill factor 100%,每次新插入或更新一个记录,由于当前页没有空间可用,可能有分页情况产生。过多的分页会降低SQL Server的性能。下面具体举个例子:

假设您在一张表上建立了一个使用默认fill factor的新索引。当SQL Server创建索引时,它会把索引放置在连续的物理页上,以使数据顺序地被读,I/O访问最优化。但当表因INSERTUPDATEDELETE等操作增长改变时,分页发生,SQL Server在磁盘的其他地方分配新的页,导致新的页与原物理页不连续,增加了随机I/O,访问索引页变慢。

 

那么fill factor的合适值应该为多少?这取决于表的读/写比:

低更新表(读/写比:1001):100% fill factor

高更新表(写超过读):50%-70% fill factor

居中:80%-90% fill factor

 

过低的fill factor会增加页的数量,也会导致更多的页需要被移至缓存,缓存中有用的数据减少。默认的fill factor0(即100% fill factor),通常这不是个好的选择,特别是对于聚集索引。

如果您无法判断设置什么fill factor,您首先需要确定磁盘的读/写比.方法就是使用如下两个计数器:

Physical Disk Object: % Disk Read Time Physical Disk Object: % Write Time。另外一个可能有用的计数器就是:SQL Server Access Methods: Pages Splits/Sec。这个计数器测量SQL Server内每秒分页的次数。如果该数值过高,您需要降低fill factor防止新的分页。

 

如果您想确认您的索引因分页产生的碎片程度,您可以运行DBCC SHOWCONTIG命令。如果看特定表和特定索引,您可以运行如下代码:

结果集中最重要的参数是Scan Density,越接近100%越好。如果Scan Density小于75%,那么您可能需要重建表中的索引。

--Script to identify table fragmentation

 

--Declare variables

DECLARE

@ID int,

@IndexID int,

@IndexName varchar(128)

 

--Set the table and index to be examined

SELECT @IndexName = 'index_name' --enter name of index

SET @ID = OBJECT_ID('table_name') --enter name of table

 

--Get the Index Values

SELECT @IndexID = IndID

FROM sysindexes

WHERE id = @ID AND name = @IndexName

 

--Display the fragmentation

DBCC SHOWCONTIG (@id, @IndexID)

 

对于小于100数据页,重建索引并不会有明显的性能改善。这是因为物理硬件缓存,SQL Server缓存和SQL Server预读机制隐藏了碎片的负面作用。但对于非常大的表,重建索引会使它受益匪浅,因为涉及大量磁盘I/O操作。

转载于:https://www.cnblogs.com/galaxyyao/archive/2009/04/10/1432971.html

### SQL Server 重建索引的语句及方法 在 SQL Server 中,重建索引是一种优化数据库性能的重要手段。通过重建索引,可以减少数据碎片、回收无效空间,并更新列统计信息以提高查询效率[^1]。以下为重建索引的常用语句示例。 #### 使用 `ALTER INDEX .. REBUILD` 语句 `ALTER INDEX` 是 SQL Server 2005 及更高版本中用于管理索引的主要语句。通过指定 `REBUILD` 选项,可以重建整个索引或特定索引。以下是具体的语法和示例: ```sql -- 重建单个索引 ALTER INDEX [索引名称] ON [名称] REBUILD; -- 示例:重建名为 IX_Employee 的索引 ALTER INDEX IX_Employee ON Employees REBUILD; ``` 如果需要重建上的所有索引,可以使用以下语句: ```sql -- 重建上所有索引 ALTER INDEX ALL ON [名称] REBUILD; -- 示例:重建 Employees 上的所有索引 ALTER INDEX ALL ON Employees REBUILD; ``` #### 使用 `sys.dm_db_index_physical_stats` 分析索引状态 在执行索引重建之前,建议先分析索引的状态以确定是否需要重建。可以使用系统函数 `sys.dm_db_index_physical_stats` 来获取索引的碎片化程度。以下是一个示例查询: ```sql SELECT OBJECT_NAME(object_id) AS TableName, name AS IndexName, avg_fragmentation_in_percent FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') WHERE index_id > 0 AND avg_fragmentation_in_percent > 30; ``` 此查询将返回平均碎片化程度超过 30% 的索引[^1]。 #### 索引重建的优点 重建索引不仅可以减少数据碎片,还可以回收因删除记录而产生的无效空间[^3]。此外,重建索引会自动更新与索引相关的列统计信息,从而帮助查询优化器选择更高效的查询计划[^2]。 #### 注意事项 - 在高并发环境中,索引重建可能会导致短暂的锁等待问题。因此,建议在低峰时段执行索引重建操作。 - 如果希望避免长时间锁定,可以考虑使用 `ALTER INDEX .. REORGANIZE` 语句来重新组织索引,但该方法不会回收无效空间。 ```sql -- 重新组织索引(非锁定) ALTER INDEX [索引名称] ON [名称] REORGANIZE; ``` ### 总结 通过使用 `ALTER INDEX .. REBUILD` 语句,可以有效地减少索引碎片并优化数据库性能。同时,结合 `sys.dm_db_index_physical_stats` 函数分析索引状态,能够更精准地决定何时进行索引重建[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值