每个新发布的SQL Server都具有越来越多的自我维护能力,但是“安全比抱歉好得多”的原则仍然是正确的:实际的数据库管理包含了对系统和用户数据库进行的周期性维护,这样才能在你的用户发现问题之前把它解决掉。
SQL Server 2000中包含了数据库维护计划向导,它可以为你自动完成所有的维护任务。然而,你需要了解,在现场和你的维护计划后面,什么是隐藏的可能给你带来麻烦的东西。
数据库维护计划是通过一系列的DBCC命令和系统存储过程实现的。DBCC的意思是数据库一致性检测(database consistency check)或者数据库控制台命令(database console command)。有非常多的写入文档的和没有写入文档的DBCC命令,但是只有一小部分可以用于维护。这里我将回顾一些与数据库维护的各个方面相关的DBCC命令和系统存储过程。
通常的数据库维护时间表都具有如下的活动。点击活动,可以获得与此相关的DBCC命令和系统存储过程。
1、检测数据库一致性和数据的完整性
DBCC CHECKDB是最广泛使用的,检测数据库中所有对象的工具。这个语句可以为每一个表和索引视图,以及文本和图像对象,检测所有的数据和索引页面的分配和结构上的完整性。DBCC CHECKDB保证了所有的数据和索引页面都正确链接,并且指针都是一致的。在指定的数据库中,用户和系统表都会被检测到。DBCC CHECKDB对数据库中每个对象都都执行DBCC CHECKALLOC和 DBCC CHECKTABLE语句,所以如果你使用DBCC CHECKDB,你就不需要再执行DBCC CHECKALLOC和DBCC CHECKTABLE了。
DBCC CHECKDB的某些选项(REPAIR_FAST, REPAIR_REBUILD 和 REPAIR_ALLOW_DATA_LOSS)需要数据库在单用户的模式下运行。如果不是单用户模式的化,语句就失败了。注意,当用户连接在上面的时候,不要将数据库设置成单用户模式。
如果你执行不带参数的DBCC CHECKDB并且发现错误的时候,你应该将你的数据库设置在单用户模式,然后尝试修复这个问题。首先,确保执行那些不会导致数据丢失的语句——REPAIR_FAST 和 REPAIR_REBUILD。如果你还是遇到错误,那么执行DBCC CHECKDB,带着参数REPAIR_ALLOW_DATA_LOSS。还要确保在显性事务中关闭语句。如果发生了可接受的数据丢失,你可以提交这个事务。否则,你还可以通过语句来回滚所作的修改。
请注意,运行DBCC CHECKDB是一项非常消耗资源的操作。你应该在限制用户在数据库服务器上的活动的时候运行这个语句。
DBCC CHECKTABLE与DBCC CHECKDB相同,除了它是在一个单个的表、索引视图或者即使是一个索引上,而不是在整个数据库上。
DBCC CHECKALLOC检测某个数据库的磁盘空间分配结构的一致性。因为DBCC CHECKDB包括了与DBCC CHECKALLOC同样的检测,那么如果执行了CHECKDB的话就没有必要再执行DBCC CHECKALLOC了。实际上,我们推荐只使用DBCC CHECKALLOC,如果用DBCC CHECKDB或者 DBCC CHECKTABLE会报告说产生分配错误的话。
DBCC CHECKCONSTRAINTS在某个数据库中,检测某些特定的约束或者全部约束的一致性。DBCC CHECKCONSTRAINTS总是在当前数据库的上下文环境中执行。
注意,DBCC CHECKCONSTRAINTS并不进行磁盘或者文件级别的一致性检测;它只是确保外键定义的一致性,同时检测约束——仅仅是确认数据有效。如果你希望检测磁盘上表和索引的一致性,你应该执行DBCC CHECKDB或者在所有的表上执行DBCC CHECKALLOC和 DBCC CHECKTABLE的组合。
首先,为什么会发生约束违规?当数据库创建的时候,外键和一致性检测也许并不存在。开发人员和数据库管理员也许使用了WITH NOCHECK选项来创建约束,这个选项只能防止约束违规的进一步扩展,而不是会检测已经存在的数据。更进一步的说,通过外键链接的数据可能会过期并且从母表中删除,但是仍然会留在相关的表中,因为它在下级表中仍然具有相关记录。
DBCC CHECKCATALOG在某个数据库的系统表内或者之间检测一致性。很多类似DBCC CHECKCONSTRAINTS的命令都不会检测页面分配的一致性;它只是检测系统表中的数据。DBCC CHECKCATALOG报告错误意味着有些人手工从系统表中添加、修改或者删除记录了。如果你没有注意此类活动,那么你应该看紧你的安全措施了——看看谁具有系统管理员和数据库主任的全县,然后评估你的安全策略。
2、重建索引
当数据行从表中INSERTED, UPDATED and DELETED的时候,索引就产生了碎片。碎片越多,索引的效率越低。数据库管理员必需确保碎片的级别很低或者根本不存在。碎片级别可以通过在某个索引上执行DBCC SHOWCONTIG语句来找到。
这里有三种方法可以去掉碎片:
1、 使用CREATE INDEX……WITH DROP EXISTING语句来删除并重新创建索引
2、 执行DBCC DBREINDEX
3、 执行DBCC INDEXDEFRAG
DBCC DBREINDEX重新构建一个特定的索引或者某个特定的表上的所有的索引。这个语句允许强制PRIMARY KEY和UNIQUE约束的索引重新构建,而不需要删除约束。你不需要知道索引的类别和名称,你同样可以使用。使用DBCC DBREINDEX比单独为表上的每个索引编写DROP INDEX 和CREATE INDEX语句简单。时刻记住,重新构建聚簇索引也会引起非聚簇索引的重建。
DBCC INDEXDEFRAG可以删除某个聚簇索引或者非聚簇索引的碎片。与DBCC DBREINDEX不同,这个语句需要指定某个特别的索引,并且不能运行在表上所有索引上。删除碎片也是一项在线操作,因此不会妨碍用户对表进行操作。DBCC INDEXDEFRAG给系统增加了额外的负担,因为它产生了额外的I/O负担。它还会影响到索引页面,并且会在压缩之后删除所有遗留的没有数据的页面。
删除碎片的频率依赖于在你的数据库中,数据修改的级别。需要每天处理几百万个事务的系统应该至少每个星期都进行一次索引重建。另一方面,在几乎没有修改的数据库上,即使你每个月进行一次索引重建,数据库都会运行得不错。
2、重建索引
当数据行从表中INSERTED, UPDATED and DELETED的时候,索引就产生了碎片。碎片越多,索引的效率越低。数据库管理员必需确保碎片的级别很低或者根本不存在。碎片级别可以通过在某个索引上执行DBCC SHOWCONTIG语句来找到。
这里有三种方法可以去掉碎片:
1、 使用CREATE INDEX……WITH DROP EXISTING语句来删除并重新创建索引
2、 执行DBCC DBREINDEX
3、 执行DBCC INDEXDEFRAG
DBCC DBREINDEX重新构建一个特定的索引或者某个特定的表上的所有的索引。这个语句允许强制PRIMARY KEY和UNIQUE约束的索引重新构建,而不需要删除约束。你不需要知道索引的类别和名称,你同样可以使用。使用DBCC DBREINDEX比单独为表上的每个索引编写DROP INDEX 和CREATE INDEX语句简单。时刻记住,重新构建聚簇索引也会引起非聚簇索引的重建。
DBCC INDEXDEFRAG可以删除某个聚簇索引或者非聚簇索引的碎片。与DBCC DBREINDEX不同,这个语句需要指定某个特别的索引,并且不能运行在表上所有索引上。删除碎片也是一项在线操作,因此不会妨碍用户对表进行操作。DBCC INDEXDEFRAG给系统增加了额外的负担,因为它产生了额外的I/O负担。它还会影响到索引页面,并且会在压缩之后删除所有遗留的没有数据的页面。
删除碎片的频率依赖于在你的数据库中,数据修改的级别。需要每天处理几百万个事务的系统应该至少每个星期都进行一次索引重建。另一方面,在几乎没有修改的数据库上,即使你每个月进行一次索引重建,数据库都会运行得不错。
3、更新统计数字
统计数据中包含了表中某个索引或者字段的数值分布的信息。你可以通过使用CREATE STATISTICS语句或者使用sp_createstatistics系统过程来创建统计数字。统计数字检索有关索引是否具有良好或者糟糕的选择性的信息,索引的选择性可以用来判断索引的效率是否足以满足查询的要求。当你创建索引的时候,SQL Server自动创建统计数字。此外,SQL Server还为那些没有定义索引的字段创建统计数字。
针对某个索引的统计数字可以通过使用DBCC SHOW_STATISTIC0S语句来查看。当数据发生改变的时候,统计数字就过时了。当选择索引来满足查询的时候,陈旧的统计数字会让SQL Server作出次优化的决定。
默认情况下,SQL Server 2000自动更新每个表上的统计数字。然而,在某些情况下,关闭统计数字的自动更新是有意义的。例如,我们假设你有某种类型的批处理例程,每个周末,系统具有最小利用率的时候,都会向你的表中添加上百万行数据。统计数字的自动更新只会降低你的批处理过程,而不会为系统带来任何好处。除了你可以在周末关闭自动更新,然后在每个周一早上首先更新统计数字之外,你还可以启用或者禁用统计数字的自动更新,通过使用sp_autostats过程。
如果你想要为单个的表或者索引更新统计数字,你可以使用UPDATE STATISTICS命令。或者你还可以执行sp_updatestats系统过程来更新当前数据库中所有表上的统计数字。
4、报告数据和日志文件中的空间利用率
也许你被要求扩展或者缩减一个数据文件或者事务日志文件的尺寸,那么这时候就可以使用DBCC SHRINKDATABASE 或者 DBCC SHRINKFILE命令了。
Sysindexes表在经过一段时间之后会变得不准确,特别是在增长频繁并且/或者缩减频繁的数据库中。DBCC UPDATEUSAGE命令报告并且纠正sysindexes表中不准确的数字。如果你认为你的数据库或者表的尺寸与sp_spaceused系统过程中报告的数字不符的话,那么你就应该使用这个语句。
每次在你使用DBCC SHRINKDATABASE 或者 DBCC SHRINKFILE缩减数据库文件之后,都执行DBCC UPDATEUSAGE,或者只是作为一个周期性的维护计划,都是个好主意。
作者简介:Kevin Kline是Quest软件公司负责SQL Server解决方案的主任。他还是国际SQL Server专家协会(Professional Association for SQL Server,PASS)的主席,并且经常为数据库技术杂志、网站以及论坛供稿。他编写了O'Reilly & Associates出版社出版的《SQL in a Nutshell》一书。作为SearchSQLServer.com 网站的监控和管理专家,Kline欢迎你向他提问。
Baya Pavliashvili是Healthstream公司(一家在线保健教育公司)的数据库管理员经理,他所管理的数据库支持了超过1百万用户。Pavliashvili主要的技术领域包括性能调整、复制和数据仓库。你可以通过baya.pavliashvili@healthstream.com来联系他。