问题一:
主机运行缓慢  可是不明白如何使用“SQL Server活动监视器”查看当前资源的占用情况,哪有使用教程?问题二:
查看到大量状态是睡眠,这个是什么意思,影不影响性能?问题三:
另外还有一些概念不明白:
什么是进程ID 、连接数、并发数?  它们有什么区别和联系?求解

解决方案 »

  1.   

    方法一    --查询索引碎片(包括系统产生的)  磁盘碎片超过30%就应该重新建立索引
    use 数据库名
    go
    SELECT  top 10 OBJECT_NAME(dt.object_id) 表和视图等对象,
    si.name 索引名,
    dt.avg_fragmentation_in_percent 外部碎片,
    dt.avg_page_space_used_in_percent 内部碎片
    FROM
    (SELECT object_id,
    index_id,
    avg_fragmentation_in_percent,
    avg_page_space_used_in_percent
    FROM    sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'DETAILED')
    WHERE   index_id <> 0
    ) AS dt --does not return information about heaps
    INNER JOIN sys.indexes si
    ON     si.object_id = dt.object_id
    AND si.index_id  = dt.index_id
    order by dt.avg_page_space_used_in_percent desc  --自己加的语句碎片的分类
    1内部碎片(avg_page_space_used_in_percent) -是说索引的大小,超过了索引的实际大小,也就是填充度 
    2外部碎片(avg_fragmentation_in_percent) -是说索引页面的排序和物理不一致,index page的newxtpage+prevpageid的是最小相临的(REORGANIZE就是解决这个问题)
    3物理连续性(fragment_count 和 avg_fragment_size_in_pages[>65 and <256]) -是说单一的分配单元的8个页面的连续性质,简单可以说是nextpage是不是当前page的+1至+7
    4内部的逻辑碎片(有聚集索引的情况) 也就是槽号的物理顺序和逻辑顺序的不同(就是很多人说的聚集索引的顺序,和物理的存储顺序是不同的)--重新组织索引
    ALTER INDEX [index_id] ON [dbo].[tbTest] REORGANIZE
    REORGANIZE的过程:
        1压缩过程 查找临近的page,查找可以移动的记录转移到小pageid的页面,增加填充度(不会分配新的index page,有些记录会因为移动,而不在先前的page里存放)
        2使逻辑和物理的顺序保持一致(这和上面的不冲突),使用中间页来互换页面内容,使页面的pageid从小到大排列,删除最后的空page
    ALTER INDEX [index_id] ON [dbo].[tbTest] REBUILD
    重建索引
    同时维护2个索引,新的创建完,会删除旧索引(因为同时维护2个版本的索引,只能分配新的索引页面,删除旧的索引页面)
    所以rebuild后的avg_fragmentation_in_percent逻辑碎片,应该是在0-3左右,avg_page_space_used_in_percent会在95以上(大型行也许会小一点)
    方法二 
    -- Create required table structure only.
    -- Note: this SQL must be the same as in the Database loop given in the -- following step.
    SELECT TOP 1 
            DatabaseName = DB_NAME()
            ,TableName = OBJECT_NAME(s.[object_id])
            ,IndexName = i.name
            ,[Fragmentation %] = ROUND(avg_fragmentation_in_percent,2)
    INTO #TempFragmentation
    FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s
    INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
        AND s.index_id = i.index_id 
    WHERE s.[object_id] = -999  -- Dummy value just to get table structure.
    ;-- Loop around all the databases on the server.
    EXEC sp_MSForEachDB    'USE [?]; 
    -- Table already exists.
    INSERT INTO #TempFragmentation 
    SELECT TOP 10
            DatabaseName = DB_NAME()
            ,TableName = OBJECT_NAME(s.[object_id])
            ,IndexName = i.name
            ,[Fragmentation %] = ROUND(avg_fragmentation_in_percent,2)
    FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s
    INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
        AND s.index_id = i.index_id 
    WHERE s.database_id = DB_ID() 
          AND i.name IS NOT NULL    -- Ignore HEAP indexes.
    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
    AND dt.avg_fragmentation_in_percent>10   --自己加的,预示对应的索引出现外部碎片
    AND dt.avg_page_space_used_in_percent<75  --自己加的,预示对应的索引出现内部碎片
    ORDER BY [Fragmentation %] DESC
    ;
    '-- Select records.(where DatabaseName='test'不加则是查询所有数据库)
    SELECT TOP 10 * FROM #TempFragmentation  where DatabaseName='test'  
    ORDER BY [Fragmentation %] DESC
    -- Tidy up.
    DROP TABLE #TempFragmentation
    索引重组:执行下面的命令:
    ALTERINDEXALLONTableNameRECOGNIZE
    索引重建:
    ALTERINDEXALLONTableNameREBUILDWITH(FILLFACTOR=90,ONLINE=ON)
     通过使用具体索引的名字代替ALL,你能重组或重建单个的索引。你也可以使用数据库控制台来重建/重组索引
    当外部碎片的值在10-15,内部碎片的值在60-75,对于这样的索引,你应该重组索引。否则,你应该重建索引。
      关于索引重建的一个重要的事情是:一旦在一个特定的表上重建索引,表就会被锁定(重组的时候不会发生)。所以,对于一个产品数据库的一个大的表,因为在一个大表上的索引重建往往需要花费数个小时,我们不希望这种锁定。幸运的是,在SQL2005有一个解决方法,你可以在重建一个表的索引的时候,把ONLINE选项的值设为ON,这样会使重建索引和表上的数据事务同样进行。
      在数据表里的所有适合创建索引的字段上创建索引,这是非常诱惑人的。但是如果你正在从事一个事务数据库工作,在每个字段上创建索引并不是每次都是需要的。事实上,在一个OLTP系统上创建大量的索引可能会降低数据库的性能。(因为当很多操作是更新操作的时候,更新数据意味着更新索引)
      一个首要的规则建议如下:
      如果你在从事一个事务性数据库,平均不要在一个表上创建超过5个索引,另外,如果你在从事数据仓库,平均最高可在一个表上创建10个索引。上个月,我仔细研究了新的sys.dm_db_index_physical_stats()表值函数(TVF)在SQL Server 2005中的用法。这个用来替代DBCC SHOWCONTIG的函数能够返回关于你的数据结构的物理组织的信息。该函数能返回任何需要物理存储的SQL Server 2005对象(包括:表、索引和索引视图)的信息。下面就让我们一起来看一下其中的一些返回信息所代表的含义是什么。 
    管用的列表
    为了对属于表或索引的页进行追踪,SQL Server使用了不同的页列表(根据SQL Server在页上存储数据的方式来组织)。此外,SQL Server 2005还新增了将一个表或索引创建在不同分区上的功能;每一个分区拥有各自的页列表。某一分区的某种类型的一个页列表就叫做一个“分配单元(Allocation Unit)”。SQL Server 2005对每一分区上的每个表或索引最多提供三个分配单元的支持。这三个分配单元分别对应于SQL Server 2005管理的三种类型的页:IN_ROW_DATA(即:常规数据或索引行)、LOB_DATA(即:大型对象数据,如:text、ntext或图像数据)、以及ROW_OVERFLOW_DATA(一个新的存储类型)。在以后的栏目中,我会对那些允许行溢出数据的数据类型作一些讨论。
    丰富的返回信息
    除了对每个表或索引在每一分区上的各个分配单元返回一行信息外, sys.dm_db_index_physical_stats()函数同样也为每个索引的各个级别返回一行信息。表1列出的内容解释了各种输出信息所代表的含义。
     
    表1:输出信息一览表
    在SQL Server 2000和7.0中,DBCC SHOWCONTIG返回四种碎片的信息:内部碎片和三种外部碎片。(附文“碎片详解”详细解释了SQL Server中的内部碎片和外部碎片之间的区别和联系。)但是,当表或索引跨越多个文件时,这两种碎片类型的报告值就显得毫无意义。而在SQL Server 2005中,跨越多个文件时的所有报告值都是有意义的。不过,每一种类型的碎片并非都与每一种结构相关。
    在SQL Server 2005中,avg_page_space_used_in_percent值报告的是内部碎片。该浮点值表示的是某个分区中某种类型的分配单元的某个特定索引级别的所有页的平均值。这是SQL Server 2005为LOB_DATA和ROW_OVERFLOW_DATA页所报告的唯一碎片类型。
    avg_fragmentation_in_percent值报告的是外部碎片。该浮点值表示的是IN_ROW_ DATA分配单元中的索引的逻辑碎片或堆的区段(extent)碎片。SQL Server对LOB_DATA和ROW_ OVERFLOW_ DATA分配单元的返回值为0。 
    逻辑碎片代表一个索引的叶级页中的无序页所占的百分比。每个叶级页在其头部都有一个指针,指向逻辑顺序的下一页;无序页指的就是那些页码低于前一页的页。例如,某个索引中存在第86页,而它的下一页却指向了第77页,则第77页就属于无序页。如果第86页的下一页指向第102页,则第102页是有序的。逻辑碎片并不关心页码是否连续,它只关心页的逻辑顺序与磁盘上的物理顺序是否一致。逻辑顺序只对于索引有意义,控制顺序的关键因素是索引关键列的数据类型和校对。
    对于堆而言,avg_fragmentation_in_percent值代表的是区段碎片。区段碎片衡量了属于堆的数据的连续性。SQL Server为表或索引分配空间的单位叫做“区段”,它由八个连续的页组成。每个区段的首页码都是8的倍数,比如:一个起始于第16页的区段与起始于第8页的区段是相连的。一个文件的首个区段起始于第0页。区段碎片计算的是同一对象的区段之间的间隙。假设从第8页和第24页开始的区段属于Table x,而从第16页开始的区段属于另一张表,那么Table x包含一个间隙和两个区段。当SQL Server扫描一个表或索引时,avg_fragmentation_in_percent值(不管它表示的是逻辑碎片还是区段碎片)越接近0,执行的性能就越好。
    通过查看碎片计数和avg_fragment_size_in_pages值,你会发现第三种类型的碎片。一个由某一分配单元的同一文件的物理连续叶级页组成的碎片;每个索引至少会有一个碎片。一个索引的碎片数最多可以与其叶级页的数目等同,前提是页处于不连续或无序的状态。如果一个索引拥有大量碎片,那么读取同等数量的页所需的I/O就会比较少,因为SQL Server可以利用Read Ahead。avg_fragment_size_in_pages的值越大,扫描数据时的性能就越好――在一定范围内成立。当avg_fragment_size_in_pages大于8页时(即:64KB――一个区段的大小),扫描的性能会相当出色。不过,在碎片大小达到32页(即:256KB)后,性能的提升就不会很明显了。碎片计数和avg_fragment_size_in_pages值只为堆和IN_ROW_DATA分配单元或索引的叶级报告。没有任何碎片大小的信息被存储,也不为索引的非叶级或者LOB_DATA或ROW_OVERFLOW_DATA分配单元报告;在这些情况下sys.dm_db_index_physical_stats()函数将返回NULL。
    调用sys.dm_db_index_physical_stats()函数的时候可以在最后加上下面任意一个参数:LIMITED、SAMPLED或DETAILED。LIMITED模式扫描一个堆的所有页,但对于索引只扫描父级页(即:位于叶级之上的页)。因此,有一些值(特别是那些需要SQL Server检查叶级页内容的值)在LIMITED模式下无法被计算并返回。例如,在LIMITED模式下,函数对avg_page_space_used_in_percent的返回值为NULL。其它这样的值还有:record_count、min_record_size_in_bytes、max_record_size_in_bytes以及avg_record_size_in_bytes。
    当表非常大时你可以考虑使用SAMPLED参数,因为一次SAMPLED扫描只查看百分之一的页。SQL Server通过查看每100页中的第一页来获得采样。然而,如果表所包含的页数少于10000,SQL Server会认为表太小并且自动将SAMPLED请求转换成DETAILED,然后对所有页进行检查。如果表是一个堆的话,则采样扫描无法报告任何碎片或碎片大小的信息。只有在SQL Server知晓属于一张表的所有页时,你才能够分析碎片。对于带有聚簇索引的表,SQL Server可以通过索引的上层级别所提供的信息来判断碎片的数量和平均尺寸,但是堆并具备用来提供这些信息的结构。
    sys.dm_db_index_physical_stats()函数还能够返回两条额外的碎片信息: forwarded_record_count和ghost_record_count(或version_ghost_record_count)。转递记录(forwarded records)只可能存在于堆中,当某个列长度不定的行的尺寸由于更新而增长且不再适合原位置时就会发生转递。如果行只是被移动了,则所有指向该行的非聚簇索引指针都必须更新,这种操作的开销相当大。经过改进,SQL Server在原位置处留下一个小型的指针,指向该行在另一页中的位置。如果一个表的转递记录很多的话,扫描的效率就会受到一定的影响。
    幽灵记录(ghost records)指的是那些逻辑上已被删除而物理上仍然存在于某一页中的行。在SQL Server的后台进程清理这些幽灵记录之前,任何新的记录都无法插入到被幽灵记录所占据的空间。当幽灵记录变得非常多时,内部碎片对于你的表来说只会有百害而无一利。ghost_record_count值显示的就是逻辑上已被删除而物理上仍存在于某一页中的行的数目。
    SQL Server清理这些记录的效率还是比较高的。version_ghost_record_count计数器显示了某个尚未完成的快照隔离事务处理所驻留的行的数目。在所有相关的事务处理被提交或回滚之前,后台进程是不会清理这些行的。
    准备移除
    新的动态管理对象sys.dm_db_index_physical_stats提供了许多与各种碎片(包括内部碎片和外部碎片)相关的信息,这些碎片有可能就存在于你的表或索引中。如果在执行有序扫描的过程中发现有碎片存在,你一定想将这些碎片移除。没问题,在后面的文章中我就会告诉你怎样移除碎片。
    附文:
    碎片详解
    作者/Kalen Delaney    译者/黄思维
    碎片(表示数据并不像理想的那样紧凑和连续)可以分为两大类:内部的和外部的。内部碎片关系到你的页上遗留了多少空闲空间以及数据的紧凑程度有多高。外部碎片则关系到页的连续性如何。
    过多的碎片并非在所有场合下都会成为很严重的问题。如果你的应用程序只是随机地访问个别行的数据,那么每页上的行数或表中行与行的接近程度之类的问题都无关紧要。访问有碎片的表中的某一行与访问没有碎片的表中的某一行执行起来一样容易。然而,如果你的应用程序正在执行有序扫描操作且需要读取表的所有或绝大多数页,那么外部碎片对扫描速度的影响就很明显了。页的连续性和有序程度越高,SQL Server执行起来就越快。
    在索引的叶级上,内部和外部碎片之间存在着一种有趣的关系。在一个聚簇索引中,叶级页就是表的数据页。具有内部碎片,就意味着页内尚有可用空间,同时也为插入新行提供了潜在空间。如果不存在内部碎片,则表中就没有可供插入新行的空间,于是SQL Server将执行一次页拆分,把页中的某些行移动到另一个位置,从而为插入新行腾出空间。这样一来,那些被移动的行的新位置很可能无法与原位置保持连续,因此拆分操作会增加外部碎片的数量。所以说,存在于表(或索引)中的可供插入的内部碎片有利于减少外部碎片的数量,缺乏内部碎片会导致外部碎片量的增加。