DBCC DBREINDEX ('数据库名.dbo.表名',索引名)
在所有的OLTP环境里,实质上所有的索引都将随着时间产生碎片。几乎所有的UPDATE、INSERT、DELETE活动都将引起索引比最初创建时变得更无组织。页拆分更多,大量的页上只有很少的数据,因此满足每个SELECT需要更多的I/O。数据和索引的碎片越多,应用程序就会更慢,数据花费的空间就更多。对此你能做什么呢?你可以定期的重建索引。
那么什么可以立即使用呢?
基本上你可以使用数据库维护向导来执行索引重建,创建维护计划来完成。如果你原意接受它固有的缺陷,这也可以使用。首先,用维护向导来配置和完成索引重建是不慎重的。它将重建每一个索引,不管它是否需要重建。如果你有一个有很多大表和大量索引的大数据库,这会出问题,因为不加区别的重建整个数据库的索引会花费很长的时间,会使你的维护窗口不可用。问题在于,要么全部重建,要么全部不重建,你根本不能以任何方式分批处理数据库的表。
那么有什么别的能做吗?你可以写一个脚本来重建选择的表的索引。这样你能对数据库分批处理以减少在重建索引时你维护窗口执行的时间。你需要将这个时间减小到最少,因为重建索引会对表执行排它锁,在重建索引期间禁止用户访问。所以你可以每周的每个工作日的晚上重建五分之一表的索引,所有的索引至少一周做一次。然而,这也是不慎重的――你将重建所有表的索引而不论数据和索引是否是有碎片。
这里推荐选择性的重建索引。你需要检查表的索引和数据的碎片,保留数据,据此操作,重建索引要用确定的且区别对待的方式。仅仅通过这样系统的方法,你可以仅重建那些实际需要重建的表的数据和索引。而且也只有这种方式能最小化索引重建的时间。在整个索引重建期间,如果你不想影响你的用户的话,减少索引重建的时间是至关重要的。
那么我们怎样可以解决呢?
可以使用命令
DBCC SHOWCONTIG()
SQLServer2000比以前版本有一个大的改进就是这个简单而又至关重要的命令。DBCC SHOWCONTIG是SQLServer提供来检查索引碎片情况的工具。在以前的版本里(7.0和更早的版本),这个命令只输出文本,如果手工处理这个命令很好,然而,要实现自动化目的,它会带来严重的问题。那意味着你要循环执行每一个表并将结果输出到文本文件,然后为了读和解释原文的输出结果以便获得你寻找的信息,需要进行烦人的结构化处理。
SQLServer2000对DBCC SHOWCONTIG()命令引进了一个关键子句,名为WITH TABLERESULTS。这意味着你能运行这个命令然后将捕获的数据直接输出到表里,而不是还需要使用XP_CMDSHELL来操作的文本文件里。
在SQLServer2000里,这意味着你能结构化的循环处理表,通过在它们上面运行DBCC SHOWCONTIG命令以将捕获碎片信息插入表中。然后你能循环使用这个结果,根据碎片的情况,选择性的进行碎片整理。可以用下面的存储过程实现:
CREATE PROCEDURE sp_defragment_indexes @maxfrag DECIMAL
AS --王成辉翻译整理,转贴请注明出处
--声明变量
SET NOCOUNT ON
DECLARE @tablename VARCHAR (128)
DECLARE @execstr VARCHAR (255)
DECLARE @objectid INT
DECLARE @objectowner VARCHAR(255)
DECLARE @indexid INT
DECLARE @frag DECIMAL
DECLARE @indexname CHAR(255)
DECLARE @dbname sysname
DECLARE @tableid INT
DECLARE @tableidchar VARCHAR(255)
--检查是否在用户数据库里运行
SELECT @dbname = db_name()
IF @dbname IN ('master', 'msdb', 'model', 'tempdb')
BEGIN
PRINT 'This procedure should not be run in system databases.'
RETURN
END
--第1阶段:检测碎片
--声明游标
DECLARE tables CURSOR FOR
SELECT convert(varchar,so.id)
FROM sysobjects so
JOIN sysindexes si
ON so.id = si.id
WHERE so.type ='U'
AND si.indid < 2
AND si.rows > 0
-- 创建一个临时表来存储碎片信息
CREATE TABLE #fraglist (
ObjectName CHAR (255),
ObjectId INT,
IndexName CHAR (255),
IndexId INT,
Lvl INT,
CountPages INT,
CountRows INT,
MinRecSize INT,
MaxRecSize INT,
AvgRecSize INT,
ForRecCount INT,
Extents INT,
ExtentSwitches INT,
AvgFreeBytes INT,
AvgPageDensity INT,
ScanDensity DECIMAL,
BestCount INT,
ActualCount INT,
LogicalFrag DECIMAL,
ExtentFrag DECIMAL)
--打开游标
OPEN tables
-- 对数据库的所有表循环执行dbcc showcontig命令
FETCH NEXT
FROM tables
INTO @tableidchar
WHILE @@FETCH_STATUS = 0
BEGIN
--对表的所有索引进行统计
INSERT INTO #fraglist
EXEC ('DBCC SHOWCONTIG (' + @tableidchar + ') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')
FETCH NEXT
FROM tables
INTO @tableidchar
END
-- 关闭释放游标
CLOSE tables
DEALLOCATE tables
-- 为了检查,报告统计结果
SELECT * FROM #fraglist
--第2阶段: (整理碎片) 为每一个要整理碎片的索引声明游标
DECLARE indexes CURSOR FOR
SELECT ObjectName, ObjectOwner = user_name(so.uid), ObjectId, IndexName, ScanDensity
FROM #fraglist f
JOIN sysobjects so ON f.ObjectId=so.id
WHERE ScanDensity <= @maxfrag
AND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0
-- 输出开始时间
SELECT 'Started defragmenting indexes at ' + CONVERT(VARCHAR,GETDATE())
--打开游标
OPEN indexes
--循环所有的索引
FETCH NEXT
FROM indexes
INTO @tablename, @objectowner, @objectid, @indexname, @frag
WHILE @@FETCH_STATUS = 0
BEGIN
SET QUOTED_IDENTIFIER ON
SELECT @execstr = 'DBCC DBREINDEX (' + '''' +RTRIM(@objectowner) + '.' + RTRIM(@tablename) + '''' +
', ' + RTRIM(@indexname) + ') WITH NO_INFOMSGS'
SELECT 'Now executing: '
SELECT(@execstr)
EXEC (@execstr)
SET QUOTED_IDENTIFIER OFF
FETCH NEXT
FROM indexes
INTO @tablename, @objectowner, @objectid, @indexname, @frag
END
-- 关闭释放游标
CLOSE indexes
DEALLOCATE indexes
-- 报告结束时间
SELECT 'Finished defragmenting indexes at ' + CONVERT(VARCHAR,GETDATE())
-- 删除临时表
DROP TABLE #fraglist
GO
使用
这个存储过程应该创建在master数据库里,以便你能在服务器上的任何用户数据库里使用。
在用户数据库里通过传递一个参数(MAXFRAG)来运行。该参数是一个百分比值。意思是任何索引的碎片扫描密度小于这个值。例如,如果你想要整理那些扫描密度小于95%的索引的碎片:
USE pubs
GO
EXEC sp_deframent_indexes 95.00
局限
这个过程依赖于的标准是扫描密度,但扫描密度对于那些跨越多个文件的索引来说不是一个有效的标准。如果你的索引确实跨越多个文件,你需要用另一个标准(如Logical Frag)来更改这个存储过程。然而,这类更改超过本文的范围;如果你的索引跨越多个文件,你需要做更多的工作。
怎样做,做什么?
这个存储过程有两个独特的部分。
第1阶段
在这部分里,存储过程通过在数据库里的每个表上运行下面的命令来检查索引碎片:
DBCC SHOWCONTIG (‘tablename') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS
命令的结果存储在预先创建的临时表#fraglist里。这里就会用到DBCC SHOWCONTIG 语句的WITH TABLERESULTS的好处,仅这一点,真正的节省了太多的以前版本得到同样结果所花费的麻烦和精力。
你应该注意该存储过程工作的数据库的表的拥有者是不是dbo,通常是。我发现我最初的版本不起作用,当时一个软件经销商给我们提供的新系统的数据库里就出现了拥有者不是dbo的表。当我在这个新系统上第一次运行我的碎片整理过程时,这个程序的缺点就暴露无遗了,最后彻底失败。这个问题实际上出现在碎片整理阶段(阶段2),因为表在这里要引用表名,而在阶段1,DBCC SHOWCONTIG命令引用的时表的ID即object_id。
第2阶段
这儿使用了另一个游标来循环处理表#fraglist里的记录,这些记录是那些扫描密度低于传给存储过程参数的那个阈值的表:
DBCC DBREINDEX()
执行的结果以输出文件的形式显示在表#fraglist的内容之后,以便你能查看表和索引的碎片,正如屏幕上所显示的那样,也可以通过查看DBCC DBREINDEX()执行的结果列表来查看采取的动作。利用这些你也能推导出每个索引重建的时间。
输出结果是什么意思?
输出示例:
上面是在Excel里打开的存储过程输出文本文件的一个截屏。为了简洁一些列已经删掉了。你需要用文本文件向导来打开它,选择固定列宽,打开导入从第三行起。
这里,你能够检查你选择检查的数据库里的表的扫描密度。
在接下来的输出文件里(DBCC SHOWCONTIG输出结果的后面),你会发现正被重建索引的每个表或索引的细节,这部分的开始和结束部分都有重建索引的开始和结束时间。如下面例子显示的那样:
为什么不使用DBCC INDEXDEFRAG()去减少阻塞?
答案是如果你想要或者需要的话就使用它。如果你需要7×24小时的在线操作,那么DBCC DBREINDEX()的排他表锁不适合你的业务,你可以使用它来代替DBCC DBREINDEX()。然而,你需要适当改变一下语法,因为它们是不相同的(谢谢,微软!)。如果你不知道它们的区别,这里有一个简单的摘要:当运行DBCC DBREINDEX()的时候,必须对表有排他锁,因为它是一个完全的,彻头彻尾的索引重建操作。而DBCC INDEXDEFRAG()就不那么完全了,在线的操作试图改善你索引的环境而不至于引起阻塞和中断OLTP(希望如此)。我必须承认我从来不用DBCC INDEXDEFRAG(),因为很幸运的是我的系统不需要严格的7×24在线且要求不阻塞,所以我不敢担保是否有效率。我已经理解它不是和DBCC DBREINDEX一样有效率。然而它的确比什么都没有强,所以如果你的数据库运行一个全球的WEB站点并且从来不能停止,这在今天这也很普遍,那么你需要使用它来代替以改变这个存储过程。
添加到调度任务里
对于有相当经验的DBA来说这是一个相关的微不足道的任务,所以我在这里不会提供它的代码。作为一个独立的任务或在你存在的维护作业里的一个步骤都行。你要确保作业的步骤或作业里的输出结果是一个文本文件以便你能保存和查看所有重要的输出文件。
结论
希望这篇文章和代码能帮助你完成一个对数据库服务器维护来说更好的更精确的方法。现在的维护窗口开销很大,所以在影响用户和执行时间上保持最小的同时也提供了有效率和良好的数据库服务器维护。用调度作业实现这个过程,小心的监控它的输出结果。
分享到:
相关推荐
SQL Server 2000的查询优化器会自动选择最佳的执行计划,包括选择合适的索引。理解查询优化器的工作原理可以帮助我们更好地设计和使用索引。 总结,SQL Server 2000的索引优化是数据库性能调优的重要环节。通过对...
根据提供的文件信息,本文将详细解析SQL Server 2000中重建索引与收缩数据库的相关知识点。 ### 一、重建索引 #### 1. 什么是索引 在SQL Server 2000中,索引是提高数据检索速度的重要工具。它可以看作是一种特殊...
- **定期维护**:包括但不限于重建索引、收缩数据库文件等操作,以保持数据库的最佳状态。 ### 结论 SQL Server 2000作为一款成熟的关系型数据库管理系统,在企业级应用中占据着重要的地位。通过对上述知识点的...
优化 SQL Server 索引的小技巧 SQL Server 中有多种可以让您检测、调整和优化 SQL ...如果你不想自动维护索引,那么你可以手工重建索引,并在需要时执行 UPDATE STATISTICS 命令来刷新 SQL Server 对于该索引的信息。
《SQL Server 2000开发者指南》是一本专为SQL Server 2000的开发者量身定制的详尽教程。SQL Server 2000是微软公司推出的一款关系型数据库管理系统(RDBMS),它在当时因其强大的功能、稳定性和可扩展性而备受青睐。...
检查索引碎片情况 1.SELECT 2.OBJECT_NAME(object_id) as objectname, 3.object_id AS objectid, 4.index_id AS indexid, 5.partition_number AS partitionnum, 6.avg_fragmentation_in_percent AS fra 7.FROM sys....
Sql server批量查询碎片率高的索引及自动重建脚本
首先,标题中的"sqlserver自动生成sql语句工具"指的是可以分析SQL Server数据库结构和数据,自动生成对应的SQL创建语句的软件。这种工具通常能帮助数据库管理员快速获取数据库的定义,便于备份、迁移或在其他环境中...
因此,重建索引是恢复索引性能的一种方式,它创建了新的索引页,并将索引数据重新排序和整理。 标题“重建所有索引”指出了一个数据库维护操作,即通过脚本或其他方式重建数据库中所有表的索引。描述中提到,随着...
2. 索引调整:创建或重建索引以提高查询性能。 3. 表分区:大型表可按特定条件(如时间)分区,加快查询速度。 4. 内存调优:合理配置服务器内存以提升性能。 在“数据库课件”中,你将深入学习这些概念和技能,为...
### SQL Server 2000 基础教程知识点概览 #### 一、数据库创建与管理 **1. 创建数据库** - **手动创建**:通过SQL Server 2000企业管理器的手动操作来新建数据库。 - **使用向导**:利用SQL Server 2000提供的...
**SQLServer索引查询优化指南** SQLServer是一个广泛使用的数据库管理系统,尤其在企业级应用中,性能优化至关重要。本指南将深入探讨SQLServer中的索引原理及其对查询优化的影响。索引是数据库性能的关键因素,它...
在SQL Server 2000中,全文索引是一项强大的功能,它允许用户进行复杂的文本搜索,大大提高了从大量文本数据中检索信息的效率。全文索引与传统的基于关键字的索引不同,它能理解词汇的语法和语义,从而提供更精确、...
达梦数据库
SQL Server 2000数据库优化方案主要针对数据库性能低下、查询速度慢等问题,通过一系列技术和策略提升数据库的运行效率。以下是对这些优化方法的详细解释: 1. **索引优化**:没有索引或未有效利用索引是查询慢的...
综上所述,SQL Server健康检查脚本是数据库管理中不可或缺的工具,它提供了一种有效、自动化的方式来监控和维护SQL Server实例的健康状态。通过定期执行这些检查,DBA能够及时发现并解决潜在问题,确保数据库系统的...
10. **索引维护**:定期重建索引(`DBCC REINDEX`)、碎片整理(`DBCC INDEXDEFRAG`)以及收缩数据库和日志(`DBCC SHRINKDB`, `DBCC SHRINKFILE`),避免性能下降。 11. **查询优化**:理解查询处理过程,包括词法...
频繁的扫描可能意味着索引使用不当或业务需求过于复杂,需要对查询优化器进行分析并考虑重建或创建合适的索引。 块裂分(page splits)的检查揭示了表数据结构的健康状况。过多的块裂分会影响插入操作的效率,可能...
提供的文档 "SqlServer2005数据库自动备份流程.doc" 可能详细介绍了如何配置 SQL Server Agent 作业以及创建备份脚本的步骤,这对于了解具体操作过程非常有用。 10. **安全性**: 记住备份文件同样需要保护,避免...