读书笔记 - 高效维护数据库的关键技巧

/***********高效维护数据库的关键技巧***********/
http://technet.microsoft.com/zh-cn/magazine/2008.08.database.aspx
1.今天第二次看到对于自动增长的建议,由于自动增长会使SQL Server出现断裂,日志文件在内部被划分为多个称为“虚拟日志文件”(VLF) 的片段,
与日志有关的操作(如为事务性复制/回滚而读取日志)、日志备份乃至 SQL Server 2000 中的触发器(触发器的实现已在 SQL Server 2005 中更改
为行版本框架,而不是事务日志)
如果数据的初始大小为 50GB,但您知道在接下来的六个月内将再添加 50GB 的数据,那么应创建 100GB 的数据文件,而不是多次将其增大以达到该
大小。
应注意不要以任何方式启用缩减。缩减可用于减小数据或日志文件的大小,但它是一个干扰很大、极耗资源的过程,但是经历过日志文件增加到100多
Gdown机的情况,只能定时自动收缩啊.ALTER DATABASE MyDatabase SET AUTO_SHRINK OFF;
2.碎片的问题
逻辑扫描碎片是由称为页面分隔的操作而引发的。当必须在特定索引页(根据索引键定义)中插入记录但页面中并没有足够的空间来容纳所插入的数
据时,便会发生这种情况。该页面会被分割一半,大约 50% 的记录被移到新分配的页面。通常,这一新页面实际上并不与旧页面相邻,因此,被称
为零碎的页面。扩展盘区扫描碎片在概念上与此类似。表格/索引结构内的碎片会影响 SQL Server 执行有效扫描的能力,无论是对整个表格/索引进
行扫描还是按查询 WHERE 子句(例如,SELECT * FROM MyTable WHERE Column1 > 100 AND Column1 < 4000)进行扫描都会受到影响。看图
 SQL Server 2005 Enterprise Edition 中,索引重新生成可以联机进行,但有几个限制。而重新组织使用原位算法对索引进行压缩并整理碎片;它
运行只需要 8KB 的额外空间,而且始终是联机运行的。在 SQL Server 2005 中,用于调查的命令为 ALTER INDEX …… REBUILD 用于重新生成索引
,ALTER INDEX … REORGANIZE 用于重新组织索引。此语法分别取代了 SQL Server 2000 中的命令 DBCC DBREINDEX 和 DBCC INDEXDEFRAG。实际上
,在 SQL Server 2000 中,我专门编写了索引重新组织代码,用于替代重新生成索引,它的优点是联机且节省空间。
+ 不要只是选择每晚或每周重新生成或重新组织所有索引,如使用维护计划选项,应该找出哪些索引被分割为碎片以及删除碎片是否会带来任何好处.
使用 DMV sys.dm_db_index_physical_stats(或 SQL Server 2000 中的 DBCC SHOWCONTIG)来定期确定哪些索引被分割为碎片,然后选择是否以及
如何对其进行操作。
***sys.dm_db_index_physical_stats http://msdn.microsoft.com/zh-cn/library/ms188917.aspx
函数的执行模式将确定为了获取此函数所使用的统计信息数据而执行的扫描级别。mode 被指定为 LIMITED、SAMPLED 或 DETAILED。
LIMITED 模式运行最快,扫描的页数最少。对于索引,只扫描 B 树的父级别页(即叶级别以上的页)。对于堆,只检查关联的 PFS 和 IAM 页;不
扫描堆的数据页。在 SQL Server 2005 中,在 LIMITED 模式下扫描堆的所有页。
在 LIMITED 模式下,compressed_page_count 为 NULL,这是因为数据库引擎只能扫描 B 树的非叶页和堆的 IAM 和 PFS 页。使用 SAMPLED 模式可
以获取 compressed_page_count 的估计值,使用 DETAILED 模式可以获取 compressed_page_count 的实际值。SAMPLED 模式将返回基于索引或堆中
所有页的 1% 样本的统计信息。如果索引或堆少于 10,000 页,则使用 DETAILED 模式代替 SAMPLED。
DETAILED 模式将扫描所有页并返回所有统计信息。
从 LIMITED 到 DETAILED 模式,速度将越来越慢,因为在每个模式中执行的任务越来越多。若要快速测量表或索引的大小或碎片级别,请使用 
LIMITED 模式。它的速度最快,并且对于索引的 IN_ROW_DATA 分配单元中的每个非叶级别,不返回与其对应的一行。
CREATE DATABASE Test;
GO
USE Test;
GO
CREATE SCHEMA Person;
GO
CREATE Table Person.Address(c1 int);
GO
SELECT * FROM sys.dm_db_index_physical_stats
    (DB_ID(N'Test'), OBJECT_ID(N'Person.Address'), NULL, NULL , 'DETAILED');
GO
USE AdventureWorks;
GO
DROP DATABASE Test;
GO
SQL Server 2008 中的碎片计算算法比 SQL Server 2000 中的更精确。因此,碎片值显得更高。例如,在 SQL Server 2000 中,如果一个表的第 
11 页和第 13 页在同一区中,而第 12 页不在该区中,该表不被视为含有碎片。但是访问这些页需要两次物理 I/O 操作,因此,在 SQL Server 
2008 中,这将算作碎片。
索引或堆的碎片级别显示在 avg_fragmentation_in_percent 列中。对于堆,此值表示堆的区碎片。对于索引,此值表示索引的逻辑碎片。与 DBCC 
SHOWCONTIG 不同,这两种情况下的碎片计算算法都会考虑跨越多个文件的存储,因而结果是精确的。
***DBCC SHOWCONTIG msdn.microsoft.com/library/aa258803
****SQL Server的信息统计 图4
请注意,可通过打开 AUTO_CREATE_STATISTICS 和 AUTO_UPDATE_STATISTICS 数据库选项自动创建和维护统计数据,如图 4 所示。这些选项默认情
况下是打开的,但如果您只是继承了数据库,请进行检查加以确认。有时统计数据可能已过时,在这种情况下可以通过对特定的统计数据集使用 
UPDATE STATISTICS 操作手动更新它们。或者,可以使用 sp_updatestats 存储过程,该过程会更新所有过时的统计数据(在 SQL Server 2000 中
,sp_updatestats 更新所有统计数据,无论期限为何)。
有关统计数据的详细信息,请参阅白皮书“SQL Server 2005 中的查询优化器所使用的统计信
息”microsoft.com/technet/prodtechnol/sql/2005/qrystats.mspx
3.损坏检测
一个最常见的问题是当发生电源故障时磁盘驱动器正在写出数据库页。如果驱动器无法在电源耗尽之前完成写操作(或者写操作已缓存,但没有足够
的备用电池来刷新驱动器的缓存),就可能在磁盘上产生不完整的页面映像。因为 8KB 数据库页实际上由 16 个连续的 512 字节扇区组成,所以这
种情况可能会发生。不完整的写操作可能写出新页面中的一些扇区,但也会留下上一页面映像中的一些扇区。这种情况称为破损页。如果发生了这一
情况,应如何检测呢?
在 SQL Server 2005 及后续版本中,提供了一种更加全面的机制,称为页面校验和,可以检查页中的任何损坏。这包括在写出页面之前编写整页校
验和,然后在重新读取该页时对其进行检测,就象检测破损页一样。在启用页面校验和之后,必须将页读入缓冲池,以某种方式进行更改,然后在其
受页面校验和保护之前将其重新写出到磁盘。
因此,最好的做法是为 SQL Server 2005 之后的版本启用页面校验和,为 SQL Server 2000 启用破损页检测。要启用页面校验和,请使用:
 ALTER DATABASE MyDatabase SET PAGE_VERIFY CHECKSUM;
要为 SQL Server 2000 启用破损页检测,请使用:
 ALTER DATABASE MyDatabase SET TORN_PAGE_DETECTION ON;
通过这些机制,您可以在某个页面出现损坏时进行检测,但只能在读取页面时进行。如何能够便于强制读取所有分配的页面?执行此操作(以及查找
其他任何类型的损坏)的最好方法是使用 DBCC CHECKDB 命令。这里有一篇作者博客里的文章"CHECKDB From Every Angle" 
(sqlskills.com/blogs/paul)
 DBCC CHECKDB ('MyDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS;

这篇文章解答了我的几个问题,笔记如下. 文章: http://technet.microsoft.com/zh-cn/magazine/2008.08.database.aspx 作者博客 http://sqlskills.com/blogs/paul/

  1. 自动增长 今天第二次看到对于自动增长的建议,由于自动增长会使SQL Server出现断裂,日志文件在内部被划分为多个称为“虚拟日志文件”(VLF) 的片段,与日志有关的操作(如为事务性复制/回滚而读取日志)、日志备份乃至 SQL Server 2000 中的触发器(触发器的实现已在 SQL Server 2005 中更改为行版本框架,而不是事务日志)
    如果数据的初始大小为 50GB,但您知道在接下来的六个月内将再添加 50GB 的数据,那么应创建 100GB 的数据文件,而不是多次将其增大以达到该大小。
    应注意不要以任何方式启用缩减。缩减可用于减小数据或日志文件的大小,但它是一个干扰很大、极耗资源的过程,但是经历过日志文件增加到100多Gdown机的情况,只能定时自动收缩啊.ALTER DATABASE MyDatabase SET AUTO_SHRINK OFF;
  2. 碎片的问题: 逻辑扫描碎片是由称为页面分隔的操作而引发的。当必须在特定索引页(根据索引键定义)中插入记录但页面中并没有足够的空间来容纳所插入的数据时,便会发生这种情况。该页面会被分割一半,大约 50% 的记录被移到新分配的页面。通常,这一新页面实际上并不与旧页面相邻,因此,被称为零碎的页面。扩展盘区扫描碎片在概念上与此类似。表格/索引结构内的碎片会影响 SQL Server 执行有效扫描的能力,无论是对整个表格/索引进行扫描还是按查询 WHERE 子句(例如,SELECT * FROM MyTable WHERE Column1 > 100 AND Column1 < 4000)进行扫描都会受到影响。看图

    SQL Server 2005 Enterprise Edition 中,索引重新生成可以联机进行,但有几个限制。而重新组织使用原位算法对索引进行压缩并整理碎片;它运行只需要 8KB 的额外空间,而且始终是联机运行的。在 SQL Server 2005 中,用于调查的命令为 ALTER INDEX …… REBUILD 用于重新生成索引,ALTER INDEX … REORGANIZE 用于重新组织索引。此语法分别取代了 SQL Server 2000 中的命令 DBCC DBREINDEXDBCC INDEXDEFRAG,或者重建索引Create Index With Drop_Existing 参看 [DBA].[IndexMaintaine].[IndexDrag_2000]。实际上,在 SQL Server 2000 中,我专门编写了索引重新组织代码,用于替代重新生成索引,它的优点是联机且节省空间。
    不要只是选择每晚或每周重新生成或重新组织所有索引,如使用维护计划选项,应该找出哪些索引被分割为碎片以及删除碎片是否会带来任何好处.使用 DMV sys.dm_db_index_physical_stats http://msdn.microsoft.com/zh-cn/library/ms188917.aspx(或 SQL Server 2000 中的 DBCC SHOWCONTIG)来定期确定哪些索引被分割为碎片,然后选择是否以及如何对其进行操作。mode 被指定为 LIMITED、SAMPLED 或 DETAILED。
    ++ LIMITED 模式运行最快,扫描的页数最少。对于索引,只扫描 B 树的父级别页(即叶级别以上的页)。对于堆,只检查关联的 PFS 和 IAM 页;不扫描堆的数据页。在 SQL Server 2005 中,在 LIMITED 模式下扫描堆的所有页。在 LIMITED 模式下,compressed_page_count 为 NULL,这是因为数据库引擎只能扫描 B 树的非叶页和堆的 IAM 和 PFS 页。使用 SAMPLED 模式可以获取 compressed_page_count 的估计值,使用 DETAILED 模式可以获取 compressed_page_count 的实际值。
    ++ SAMPLED 模式将返回基于索引或堆中所有页的 1% 样本的统计信息。如果索引或堆少于 10,000 页,则使用 DETAILED 模式代替 SAMPLED。
    ++ DETAILED 模式将扫描所有页并返回所有统计信息。
    从 LIMITED 到 DETAILED 模式,速度将越来越慢,因为在每个模式中执行的任务越来越多。若要快速测量表或索引的大小或碎片级别,请使用 LIMITED 模式。它的速度最快,并且对于索引的 IN_ROW_DATA 分配单元中的每个非叶级别,不返回与其对应的一行。
    1.           
      CREATE DATABASE Test;
      GO
      USE Test;
      GO
      CREATE SCHEMA Person;
      GO
      CREATE Table Person.Address(c1 int );
      GO
      SELECT * FROM sys.dm_db_index_physical_stats
      (
      DB_ID (N ' Test ' ), OBJECT_ID (N ' Person.Address ' ), NULL , NULL , ' DETAILED ' );
      GO
      USE AdventureWorks;
      GO
      DROP DATABASE Test;
      GO
    SQL Server 2008 中的碎片计算算法比 SQL Server 2000 中的更精确。因此,碎片值显得更高。例如,在 SQL Server 2000 中,如果一个表的第 11 页和第 13 页在同一区中,而第 12 页不在该区中,该表不被视为含有碎片。但是访问这些页需要两次物理 I/O 操作,因此,在 SQL Server 2008 中,这将算作碎片。索引或堆的碎片级别显示在 avg_fragmentation_in_percent 列中。对于堆,此值表示堆的区碎片。对于索引,此值表示索引的逻辑碎片。与 DBCC SHOWCONTIG http://msdn.microsoft.com/zh-cn/library/aa258803(en-us,SQL.80).aspx 不同,这两种情况下的碎片计算算法都会考虑跨越多个文件的存储,因而结果是精确的。
          
    create index idx_charge_no on charge(charge_no)
    dbcc showcontig(charge,idx_charge_no)
    - 扫描页数................................: 186 -- 这个索引占了186个数据页
    - 扫描区数..............................: 24 -- 这些数据页分布在24个extent中
    - 区切换次数..............................: 23 -- 由于一个extent是连续的8个页所以186/8与等于24
    - 每个区的平均页数........................: 7.8
    - 扫描密度 [ 最佳计数:实际计数 ] .......: 100.00 % [ 24:24 ]
    - 逻辑扫描碎片 ..................: 0.54 %
    - 区扫描碎片 ..................: 33.33 %
    - 每页的平均可用字节数........................: 31.5
    - 平均页密度(满).....................: 99.61 %

     



  3. SQL Server的信息统计 图4请注意,可通过打开 AUTO_CREATE_STATISTICS 和 AUTO_UPDATE_STATISTICS 数据库选项自动创建和维护统计数据,如图 4 所示。这些选项默认情况下是打开的,但如果您只是继承了数据库,请进行检查加以确认。有时统计数据可能已过时,在这种情况下可以通过对特定的统计数据集使用 UPDATE STATISTICS 操作手动更新它们。或者,可以使用 sp_updatestats 存储过程,该过程会更新所有过时的统计数据(在 SQL Server 2000 中,sp_updatestats 更新所有统计数据,无论期限为何)。有关统计数据的详细信息,请参阅白皮书“SQL Server 2005 中的查询优化器所使用的统计信息”http://technet.microsoft.com/zh-cn/library/cc966419(en-us).aspx

  4. 损坏检测 一个最常见的问题是当发生电源故障时磁盘驱动器正在写出数据库页。如果驱动器无法在电源耗尽之前完成写操作(或者写操作已缓存,但没有足够的备用电池来刷新驱动器的缓存),就可能在磁盘上产生不完整的页面映像。因为 8KB 数据库页实际上由 16 个连续的 512 字节扇区组成,所以这种情况可能会发生。不完整的写操作可能写出新页面中的一些扇区,但也会留下上一页面映像中的一些扇区。这种情况称为破损页。如果发生了这一情况,应如何检测呢?在 SQL Server 2005 及后续版本中,提供了一种更加全面的机制,称为页面校验和,可以检查页中的任何损坏。这包括在写出页面之前编写整页校验和,然后在重新读取该页时对其进行检测,就象检测破损页一样。在启用页面校验和之后,必须将页读入缓冲池,以某种方式进行更改,然后在其受页面校验和保护之前将其重新写出到磁盘。因此,最好的做法是为 SQL Server 2005 之后的版本启用页面校验和,为 SQL Server 2000 启用破损页检测。要启用页面校验和,请使用: ALTER DATABASE MyDatabase SET PAGE_VERIFY CHECKSUM;要为 SQL Server 2000 启用破损页检测,请使用: ALTER DATABASE MyDatabase SET TORN_PAGE_DETECTION ON;通过这些机制,您可以在某个页面出现损坏时进行检测,但只能在读取页面时进行。如何能够便于强制读取所有分配的页面?执行此操作(以及查找其他任何类型的损坏)的最好方法是使用 DBCC CHECKDB 命令。这里有一篇作者博客里的文章"CHECKDB From Every Angle" DBCC CHECKDB ('MyDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS;

你可能感兴趣的:(读书笔记)