SQL索引的碎片处理?

idajdkaskdja 2011-04-15 02:34:17
RT
...全文
144 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
--小F-- 2011-04-15
  • 打赏
  • 举报
回复
常规经验是磁盘碎片超过30%就应该重新建立索引了
--小F-- 2011-04-15
  • 打赏
  • 举报
回复
--查询数据库db中表tb的所有索引的碎片情况
use db
go
select
a.index_id,---索引编号
b.name,---索引名称
avg_fragmentation_in_percent---索引的逻辑碎片
from
sys.dm_db_indx_physical_stats(db_id(),object_id(N'create.consume'),null,null,null) as a
join
sys.indexes as b
on
a.object_id=b.object_id
and
a.index_id=b.index_id
go

---解释下sys.dm_db_indx_physical_stats的参数
datebase_id: 数据库编号,可以使用db_id()函数获取指定数据库名对应的编号。
object_id: 该索引所属表或试图的编号
index_id: 该索引的编号
partition_number:对象中分区的编号
mode:模式名称,用于指定获取统计信息的扫描级别。


有关sys.dm_db_indx_physical_stats的结果集中的字段名去查下联机丛书。
rucypli 2011-04-15
  • 打赏
  • 举报
回复
无论何时对基础数据执行插入、更新或删除操作,SQL Server 2005 Database Engine 都会自动维护索引。随着时间的推移,这些修改可能会导致索引中的信息分散在数据库中(含有碎片)。当索引包含的页中的逻辑排序(基于键值)与数据文件中的物理排序不匹配时,就存在碎片。碎片非常多的索引可能会降低查询性能,导致应用程序响应缓慢。有关详细信息,请参阅此 Microsoft 网站。

在 SQL Server 2005 中,可以通过重新组织索引或重新生成索引来修复索引碎片。

对于基于分区方案生成的已分区索引,可以在完整索引或索引的单个分区上使用下列方法之一。

检测碎片
决定使用哪种碎片整理方法的第一步是分析索引以确定碎片程度。使用系统函数 sys.dm_db_index_physical_stats 可以检测特定索引、表或索引视图的所有索引、一个数据库中的所有索引或所有数据库中的所有索引中的碎片。例如,逻辑碎片(索引中的无序页)的百分比显示在 avg_fragmentation_in_percent 列中。对于已分区索引,sys.dm_db_index_physical_stats 还提供每个分区的碎片信息。

此函数返回的结果集包含以下几列:

列 说明
avg_fragmentation_in_percent
逻辑碎片(索引中的无序页)的百分比。

fragment_count
索引中的碎片(物理上连续的叶页)数量。

avg_fragment_size_in_pages
索引中一个碎片的平均页数。


知道碎片程度后,可以使用下表确定修复碎片的最佳方法。

avg_fragmentation_in_percent 值 修复语句
< = 30%
ALTER INDEX REORGANIZE

> 30%
ALTER INDEX REBUILD WITH (ONLINE = ON)*


*重新组织索引的操作通常是联机执行的,尽管重新生成索引的操作联机或脱机都可以执行。若要获得与重新组织选项相似的可用性,应联机重新生成索引。

例如,执行以下语句:

复制代码
USE AdventureWorks;
GO
SELECT a.index_id, name, avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(), OBJECT_ID(N'Production.Product'),
NULL, NULL, NULL) AS a
JOIN sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id;
GO


该语句可能返回与以下结果集相似的结果集:

复制代码
index_id name avg_fragmentation_in_percent
----------- --------------------------- ----------------------------
1 PK_Product_ProductID 23.076923076923077
2 AK_Product_ProductNumber 50.0
3 AK_Product_Name 66.666666666666657
4 AK_Product_rowguid 50.0

(4 row(s) affected)


通过使用上面的表,建议的解决方法是重新组织 PK_Product_ProductID 并重新生成其他索引。

若要检测碎片,应使用 sys.dm_db_index_physical_stats 动态管理函数,而不是 DBCC SHOWCONTIG。

重新组织索引
若要重新组织一个或多个索引,可以使用带 REORGANIZE 子句的 ALTER INDEX 语句。此语句可以替代 DBCC INDEXDEFRAG 语句。若要重新组织已分区索引的单个分区,可以使用 ALTER INDEX 的 PARTITION 子句。

重新组织索引是通过对叶页进行物理重新排序,使其与叶节点的逻辑顺序(从左到右)相匹配,从而对表或视图的聚集索引和非聚集索引的叶级别进行碎片整理。使页有序可以提高索引扫描的性能。索引在分配给它的现有页内重新组织,而不会分配新页。如果索引跨越多个文件,将一次重新组织一个文件,不会在文件之间迁移页。

重新组织还会压缩索引页。如果还有可用的磁盘空间,将删除此压缩过程中生成的所有空页。压缩基于 sys.indexes 目录视图中的填充因子值。

重新组织进程使用最少的系统资源。而且,重新组织是自动联机执行的。该进程不持有长期阻塞锁,所以不会阻止运行查询或更新。

索引碎片不太多时,可以重新组织索引。请参阅上面的表,了解有关碎片的指导原则。不过,如果索引碎片非常多,重新生成索引则可以获得更好的结果。

大型对象数据类型压缩
重新组织索引时,除了重新组织一个或多个索引外,默认情况下还将压缩聚集索引或基础表中包含的大型对象数据类型 (LOB)。数据类型 image、text、ntext、varchar(max)、nvarchar(max)、varbinary(max) 和 xml 都是大型对象数据类型。压缩这些数据可以更好地利用磁盘空间。

重新组织指定的聚集索引将压缩该聚集索引的叶级别(数据行)包含的所有 LOB 列。


重新组织非聚集索引将压缩该索引中属于非键(包含性)列的所有 LOB 列。


如果指定 ALL,将重新组织与指定的表或视图相关联的所有索引,并压缩与聚集索引、基础表或带有包含性列的非聚集索引相关联的所有 LOB 列。


如果 LOB 列不存在,则忽略 LOB_COMPACTION 子句。



重新生成索引
重新生成索引将删除该索引并创建一个新索引。此过程中将删除碎片,通过使用指定的或现有的填充因子设置压缩页来回收磁盘空间,并在连续页中对索引行重新排序(根据需要分配新页)。这样可以减少获取所请求数据所需的页读取数,从而提高磁盘性能。

可以使用下列方法重新生成聚集索引和非聚集索引:

带 REBUILD 子句的 ALTER INDEX。这将替代 DBCC DBREINDEX。


带 DROP_EXISTING 子句的 CREATE INDEX。


每个方法执行的功能都相同,但如下表所示,也都各有优缺点需要考虑。

功能 ALTER INDEX REBUILD CREATE INDEX WITH DROP_EXISTING
可以通过添加或删除键列、更改列顺序或更改列排序顺序来更改索引定义。*

是**

可以设置或修改索引选项。



可以在单个事务中重新生成多个索引。



可以联机重新生成大部分索引类型,而不会阻止运行查询或更新。



已分区索引可以重新分区。



可以将索引移动到另一个文件组中。



需要额外的临时磁盘空间。



重新生成聚集索引的操作将重新生成相关的非聚集索引。


除非指定关键字 ALL。


除非更改索引定义。

可以重新生成强制 PRIMARY KEY 和 UNIQUE 约束的索引,而不用删除并重新创建这些约束。



可以重新生成单个索引分区。




*通过在索引定义中指定 CLUSTERED,可以将非聚集索引转换成聚集索引类型。执行此操作时必须将 ONLINE 选项设置为 OFF。不管将 ONLINE 设置成什么,都不支持从聚集索引到非聚集索引的转换。

**如果通过使用相同的名称、列和排序顺序重新创建索引,则可以省略排序操作。重新生成操作将检查行是否在生成索引时进行了排序。

您也可以先使用 DROP INDEX 语句删除索引,然后使用一个单独的 CREATE INDEX 语句重新创建该索引,通过这种方式重新生成索引。将这些操作作为单独的语句执行有许多缺点,因此不推荐这样做。

在重新生成操作期间禁用非聚集索引以减少磁盘空间
禁用非聚集索引后,将删除索引数据行,但索引定义仍在元数据中。重新生成索引后即启用该索引。如果不禁用非聚集索引,重新生成操作需要足够的临时磁盘空间才能同时存储新旧索引。但是,通过在单独的事务中禁用并重新生成非聚集索引,禁用索引所释放的磁盘空间可重新用于随后的重新生成或其他任何操作。除了用于排序的临时磁盘空间外,不需要额外的空间。这通常是索引大小的 20%。如果非聚集索引在主键上,将自动禁用引用 FOREIGN KEY 的任何活动约束。必须在重新生成索引后手动启用这些约束。有关详细信息,请参阅禁用索引和启用索引和约束指南。

重新生成大型索引
带有多于 128 个区的索引通过两个单独的阶段重新生成:逻辑阶段和物理阶段。在逻辑阶段,索引使用的现有分配单元被标记为取消分配,数据行被复制并排序然后移动到为存储重新生成的索引而创建的新分配单元中。在物理阶段,先前标记为取消分配的分配单元在发生在后台的短事务中被物理删除,而且不需要很多锁。有关详细信息,请参阅删除并重新生成大型对象。

设置索引选项
重新组织索引时不能指定索引选项。但是,通过使用 ALTER INDEX REBUILD 或 CREATE INDEX WITH DROP_EXISTING,可以在重新生成索引时设置下列索引选项:

PAD_INDEX
DROP_EXISTING(仅 CREATE INDEX)

FILLFACTOR
ONLINE

SORT_IN_TEMPDB
ALLOW_ROW_LOCKS

IGNORE_DUP_KEY
ALLOW_PAGE_LOCKS

STATISTICS_NORECOMPUTE
MAXDOP

注意:
如果不需要执行排序操作,或者可以在内存中进行排序,则忽略 SORT_IN_TEMPDB 选项。



另外,ALTER INDEX 语句中的 SET 子句允许您设置下列索引选项,而不用重新生成索引:

ALLOW_PAGE_LOCKS
IGNORE_DUP_KEY

ALLOW_ROW_LOCKS
STATISTICS_NORECOMPUTE


有关详细信息,请参阅设置索引选项。

重新生成或重新组织索引

ALTER INDEX (Transact-SQL)

通过在一个步骤中删除并重新创建索引来重新生成索引

CREATE INDEX (Transact-SQL)
idajdkaskdja 2011-04-15
  • 打赏
  • 举报
回复
谢谢,稻子姐姐!!!
  • 打赏
  • 举报
回复
可以结贴了

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧