SQLSERVER完全优化教程

  1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)

  我们把这种 正文内容 本身就是一种按照一定规则排列的 目录 称为“聚集索引”。

  需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。我们把这种目录纯粹是目录,正文纯粹是正文的排序方式 称为“非聚集索引”。

 

  下面的表总结了何时使用聚集索引或非聚集索引(很重要):

 

  动作描述             使用聚集索引         使用非聚集索引

  列经常被分组排序      应          应

  返回某范围内的数据    应          不应

  一个或极少不同值      不应            不应

  小数目的不同值       应          不应

  大数目的不同值       不应            应

  频繁更新的列     不应            应

  外键列           应          应

  主键列           应          应

  频繁修改索引列       不应            应

 

  事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把聚合索引建立在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。

 

  结合实际,谈索引使用的误区

 

  理论的目的是应用。虽然我们刚才列出了何时应使用聚集索引或非聚集索引,但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析。下面我们将根据在实践中遇到的实际问题来谈一下索引使用的误区,以便于大家掌握索引建立的方法。

 

1、主键就是聚集索引

  这种想法笔者认为是极端错误的,是对聚集索引的一种浪费。虽然SQL SERVER默认是在主键上建立聚集索引的。

  通常,我们会在每个表中都建立一个ID列,以区分每条数据,并且这个ID列是自动增大的,步长一般为1。我们的这个办公自动化的实例中的列Gid就是如此。此时,如果我们将这个列设为主键,SQL SERVER会将此列默认为聚集索引。这样做有好处,就是可以让您的数据在数据库中按照ID进行物理排序,但笔者认为这样做意义不大。

  显而易见,聚集索引的优势是很明显的,而每个表中只能有一个聚集索引的规则,这使得聚集索引变得更加珍贵。

  从我们前面谈到的聚集索引的定义我们可以看出,使用聚集索引的最大好处就是能够根据查询要求,迅速缩小查询范围,避免全表扫描。在实际应用中,因为ID号是自动生成的,我们并不知道每条记录的ID号,所以我们很难在实践中用ID号来进行查询。这就使让ID号这个主键作为聚集索引成为一种资源浪费。其次,让每个ID号都不同的字段作为聚集索引也不符合“大数目的不同值情况下不应建立聚合索引”规则;当然,这种情况只是针对用户经常修改记录内容,特别是索引项的时候会负作用,但对于查询速度并没有影响。

  在办公自动化系统中,无论是系统首页显示的需要用户签收的文件、会议还是用户进行文件查询等任何情况下进行数据查询都离不开字段的是“日期”还有用户本身的“用户名”。

  通常,办公自动化的首页会显示每个用户尚未签收的文件或会议。虽然我们的where语句可以仅仅限制当前用户尚未签收的情况,但如果您的系统已建立了很长时间,并且数据量很大,那么,每次每个用户打开首页的时候都进行一次全表扫描,这样做意义是不大的,绝大多数的用户1个月前的文件都已经浏览过了,这样做只能徒增数据库的开销而已。事实上,我们完全可以让用户打开系统首页时,数据库仅仅查询这个用户近3个月来未阅览的文件,通过“日期”这个字段来限制表扫描,提高查询速度。如果您的办公自动化系统已经建立的2年,那么您的首页显示速度理论上将是原来速度8倍,甚至更快。

  在这里之所以提到“理论上”三字,是因为如果您的聚集索引还是盲目地建在ID这个主键上时,您的查询速度是没有这么高的,即使您在“日期”这个字段上建立的索引(非聚合索引)。下面我们就来看一下在1000万条数据量的情况下各种查询的速度表现(3个月内的数据为25万条):

 

(1)仅在主键上建立聚集索引,并且不划分时间段:

 

Select gid,fariqi,neibuyonghu,title from tgongwen

用时:128470毫秒(即:128秒)

 

(2)在主键上建立聚集索引,在fariq上建立非聚集索引:

 

select gid,fariqi,neibuyonghu,title from Tgongwen

where fariqi> dateadd(day,-90,getdate())

用时:53763毫秒(54秒)

 

(3)将聚合索引建立在日期列(fariqi)上:

 

select gid,fariqi,neibuyonghu,title from Tgongwen

where fariqi> dateadd(day,-90,getdate())

用时:2423毫秒(2秒)

 

  虽然每条语句提取出来的都是25万条数据,各种情况的差异却是巨大的,特别是将聚集索引建立在日期列时的差异。事实上,如果您的数据库真的有1000万容量的话,把主键建立在ID列上,就像以上的第1、2种情况,在网页上的表现就是超时,根本就无法显示。这也是我摒弃ID列作为聚集索引的一个最重要的因素。得出以上速度的方法是:在各个select语句前加:

 

declare @d datetime

set @d=getdate()

并在select语句后加:

 

select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())

2、只要建立索引就能显著提高查询速度

  事实上,我们可以发现上面的例子中,第2、3条语句完全相同,且建立索引的字段也相同;不同的仅是前者在fariqi字段上建立的是非聚合索引,后者在此字段上建立的是聚合索引,但查询速度却有着天壤之别。所以,并非是在任何字段上简单地建立索引就能提高查询速度。

  从建表的语句中,我们可以看到这个有着1000万数据的表中fariqi字段有5003个不同记录。在此字段上建立聚合索引是再合适不过了。在现实中,我们每天都会发几个文件,这几个文件的发文日期就相同,这完全符合建立聚集索引要求的:“既不能绝大多数都相同,又不能只有极少数相同”的规则。由此看来,我们建立“适当”的聚合索引对于我们提高查询速度是非常重要的。

 

3、把所有需要提高查询速度的字段都加进聚集索引,以提高查询速度

  上面已经谈到:在进行数据查询时都离不开字段的是“日期”还有用户本身的“用户名”。既然这两个字段都是如此的重要,我们可以把他们合并起来,建立一个复合索引(compound index)。

  很多人认为只要把任何字段加进聚集索引,就能提高查询速度,也有人感到迷惑:如果把复合的聚集索引字段分开查询,那么查询速度会减慢吗?带着这个问题,我们来看一下以下的查询速度(结果集都是25万条数据):(日期列fariqi首先排在复合聚集索引的起始列,用户名neibuyonghu排在后列):

 

(1)select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>''2004-5-5''

查询速度:2513毫秒

 

(2)select gid,fariqi,neibuyonghu,title from Tgongwen

            where fariqi>''2004-5-5'' and neibuyonghu=''办公室''

查询速度:2516毫秒

 

(3)select gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu=''办公室''

查询速度:60280毫秒

 

  从以上试验中,我们可以看到如果仅用聚集索引的起始列作为查询条件和同时用到复合聚集索引的全部列的查询速度是几乎一样的,甚至比用上全部的复合索引列还要略快(在查询结果集数目一样的情况下);而如果仅用复合聚集索引的非起始列作为查询条件的话,这个索引是不起任何作用的。当然,语句1、2的查询速度一样是因为查询的条目数一样,如果复合索引的所有列都用上,而且查询结果少的话,这样就会形成“索引覆盖”,因而性能可以达到最优。同时,请记住:无论您是否经常使用聚合索引的其他列,但其前导列一定要是使用最频繁的列。

 

四、其他书上没有的索引使用经验总结

 

1、用聚合索引比用不是聚合索引的主键速度快

  下面是实例语句:(都是提取25万条数据)

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''

使用时间:3326毫秒

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid<=250000

使用时间:4470毫秒

 

这里,用聚合索引比用不是聚合索引的主键速度快了近1/4。

 

2、用聚合索引比用一般的主键作order by时速度快,特别是在小数据量情况下

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by fariqi

用时:12936

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by gid

用时:18843

 

  这里,用聚合索引比用一般的主键作order by时,速度快了3/10。事实上,如果数据量很小的话,用聚集索引作为排序列要比使用非聚集索引速度快得明显的多;而数据量如果很大的话,如10万以上,则二者的速度差别不明显。

 

3、使用聚合索引内的时间段,搜索时间会按数据占整个数据表的百分比成比例减少,而无论聚合索引使用了多少个:

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-1-1''

用时:6343毫秒(提取100万条)

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-6-6''

用时:3170毫秒(提取50万条)

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''

用时:3326毫秒(和上句的结果一模一样。如果采集的数量一样,那么用大于号和等于号是一样的)

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen

            where fariqi>''2004-1-1'' and fariqi<''2004-6-6''

用时:3280毫秒

 

4、日期列不会因为有分秒的输入而减慢查询速度

  下面的例子中,共有100万条数据,2004年1月1日以后的数据有50万条,但只有两个不同的日期,日期精确到日;之前有数据50万条,有5000个不同的日期,日期精确到秒。

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen

          where fariqi>''2004-1-1'' order by fariqi

用时:6390毫秒

 

select gid,fariqi,neibuyonghu,reader,title from Tgongwen

            where fariqi<''2004-1-1'' order by fariqi

用时:6453毫秒

 

五、其他注意事项

 

  “水可载舟,亦可覆舟”,索引也一样。索引有助于提高检索性能,但过多或不当的索引也会导致系统低效。因为用户在表中每加进一个索引,数据库就要做更多的工作。过多的索引甚至会导致索引碎片。

  所以说,我们要建立一个“适当”的索引体系,特别是对聚合索引的创建,更应精益求精,以使您的数据库能得到高性能的发挥。

  当然,在实践中,作为一个尽职的数据库管理员,您还要多测试一些方案,找出哪种方案效率最高、最为有效。

 

 

 

 

 

 

 

 

 

 

大家都知道LIKE查询很慢,全文索引就是事先做好相关的索引,表示哪个主题词可以在哪些记录里找到,甚至事先计算好RANK,检索时可以把相关度高的先列出来,这可以大大提高检索的速度。

 

打个比方,你有很多的小抽屉,每个抽屉里面放一些杂物,假如你要找东西,最原始的方法就是一个个抽屉翻,这就是没有索引的情况。

 

假如聪明一点,给抽屉编号(唯一键),把哪个号码的抽屉有什么东西记录在纸上,找东西先看看这张纸,这就是普通索引,假如你要知道哪个抽屉有什么,你可以在纸上迅速找到抽屉号码(大家知道这是使用查找树),然后得到相关的信息,这种情况普通索引是很快的;但是要找到一个特定的东西哪些抽屉有,你就要把整张纸遍历一次,这就是LIKE查询,假如你要找哪些抽屉同时有2种甚至更多种物品,LIKE就更加繁琐了。假如一个表有上千万的纪录,大家可以想象查询的代价。

 

可以换一个思路,另外找张纸,记录一样东西存在于哪些抽屉:

 

夹子:1,3,4,5,6,9,12...

 

钱币:2,3,4,7,12...

 

药丸:1,3,5,6...

 

这样找到某样东西或者某几样东西都很容易。

 

全文索引和普通的SQL索引有很多的区别:

 

普通 SQL 索引

 

全文索引

 

存储时受定义它们所在的数据库的控制。

 

存储在文件系统中,但通过数据库管理。

 

每个表允许有若干个普通索引。

 

每个表只允许有一个全文索引。

 

当对作为其基础的数据进行插入、更新或删除时,它们自动更新。

 

将数据添加到全文索引称为填充,全文索引可通过调度或特定请求来请求,也可以在添加新数据时自动发生。

 

不分组。

 

在同一个数据库内分组为一个或多个全文目录。

 

使用 SQL Server 企业管理器、向导或 Transact-SQL 语句创建和除去。

 

使用 SQL Server 企业管理器、向导或存储过程创建、管理和除去。

 

使用全文索引的话,可以看看下面的帖子(感谢大力和lihonggen0):

 

如何在sqlserver中建立全文索引:

 

http://www.csdn.net/develop/Read_Article.asp?Id=17137

 

 

 

如何使用image字段:

 

http://expert.csdn.net/Expert/topic/1594/1594455.xml

 

发现大家有一个常问的问题,就是关于以下的信息的:

 

查询子句只包含被忽略的词

 

这是因为使用一些很简单的词,比如'是',进行查询的缘故。

 

提出的解决办法不外乎是把C:\Program Files\Microsoft SQL Server\MSSQL\FTDATA\SQLServer\Config\noise.chs 清空

 

觉得这种方法是不可取的,大家打开这个文件看看,发现里面是一些这样的词:is,are,be,at,我,是

 

这些词都是频率很高的词,而且在查询中的意义不大,就好像几乎每个抽屉里面都有纸屑一样,为这些词作索引得不偿失,所以全文引擎把这些词称为干扰词不做索引,个人觉得在应用中过滤这些词然后向用户提出友好的提示更好,而不是使用清空noise.chs粗暴的对待全文引擎。比方大家可以看看在Google中搜索“的”

 

-------------------------------------------------------------------------

 

另外谢谢ghj,一个很重要的东西遗漏了,与一般的索引立即更新不同,全文索引一般是定期维护索引的,所以对于频繁更新的数据不合适,需要做全文索引的对象一般都是论文网页之类,还算适合拉!

 

个人觉得我的数据库没有代表性,所以也不细说:作索引的时候,CPU和内存使用都很高,时间也很长(下面我的数据库是整个晚上),完成以后并不需要使用很多的系统资源,多个全文查询并发的时候也有不小的CPU消耗,但是比LIKE强。

 

我的系统上数据库是123M,太小,使用全文索引没有感到特别的优势,但是可以想想对于GOOGLE那样的海量数据,使用LIKE是不可想象的:)当然别人也没有使用关系数据库。

 

 

1.概念

         索引是在数据库表或者视图上创建的对象,目的是为了加快对表或视图的查询的速度(简单理解)。

         索引是一个单独的、物理的数据库结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单(深刻理解)。

         按照存储方式分为:聚集与非聚集索引(需要重视和区别的概念,后面详解)

         按照维护与管理索引角度分为:唯一索引、复合索引和系统自动创建的索引(相对简单,如下解释:)

         1).唯一索引:惟一索引可以确保索引列不包含重复的值.

         可以用多个列,但是索引可以确保索引列中每个值组合都是唯一的,

         即下面的姓不能有重复,同时名也不能有重复:

                                             姓      名

                                             李      二

                                             张      三

                                             王      五

          语法: create unique index idxempid on emp(姓,名)

 

          2).复合索引:如果在两上以上的列上创建一个索引,则称为复合索引。

          那么,不可能有两行的姓和名是重复的,即上面的表没有两行其姓和名的组合是一样的。

          语法: create index indxfullname on emp(姓,名)

 

          3).系统自建的索引:在使用T_sql语句创建表的时候使用PRIMARY KEY或UNIQUE约束时,会在表上

          自动创建一个惟一索引,自动创建的索引是无法删除的。

           语法:

                   create table ABC

                   ( empID int PRIMARY KEY,

                      firstname varchar(50) UNIQUE,

                      lastname  varchar(50) UNIQUE,

                     )    /*这样的结果就出来了三个索引,但只有一个聚集索引empID*/

 

 

 

         索引的结构是由:根节点--->非叶节点--->非叶节点--->叶节点(注意索引在数据库引擎中所用的

         内部数据结构一般是B+树,参考后文)

 

          聚集索引和非聚集索引——  

         用一个现实中的例子说明以助理解。我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼音排序汉字的字典是以英文字母“a”开头并以“z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。

  我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。

 

  如果您认识某个字,您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。

        我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。

 

         2.性质及使用方法

         1)聚集索引:表中存储的数据按照索引的顺序存储,检索效率比普通索引高,索引占用硬盘

          存储空间小(1%左右),但对数据新增/修改/删除的速度影响比较大(降低)。

          特点:

                  (1) 无索引,数据无序

                  (2) 有索引,数据与索引同序

                  (3) 数据会根据索引键的顺序重新排列数据

                  (4) 一个表只能有一个索引

                  (5) 叶节点的指针指向的数据也在同一位置存储

         语法:create CLUSTERED INDEX idxempID ON emp(empID)

 

         2)非聚集索引:不影响表中的数据存储顺序,检索效率比聚集索引低,索引占用硬盘存储

         空间大(30%~40%),对数据新增/修改/删除的影响很少。

         特点:

               (1) 一个表可以最多可以创建249个非聚集索引

               (2) 先建聚集索引才能创建非聚集索引

               (3) 非聚集索引数据与索引不同序

               (4) 数据与非聚集索引在不同位置

               (5) 非聚集索引在叶节点上存储,在叶节点上有一个“指针”直接指向要查询的数据区域

               (6) 数据不会根据非聚集索引键的顺序重新排列数据

         语法:create NONCLUSTERED INDEX idximpID ON emp(empID)

 

        

         创建索引的方法:

         1)企业管理器中

               (1)右击某个表,所有任务---管理索引,打开管理索引,单击“新建”就可以创建索引

               (2)在设计表中进行设计表,管理索引/键

               (3)在关系图中,添加表后右击关系图中的某个表,就有“索引/键”

               (4)通过向导,数据库---创建索引向导

               (5)通过T-SQL语句

         2)能过“索引优化向导”来优化索引的向导,通过它可以决定选择哪些列做为索引列

        

         何时应使用聚集索引或非聚集索引

         3.数据库引擎中索引的内部结构

         有必要先说明一下数据库引擎,

         这部分是较深的内容,需要有一定的数据库理论知识和数据结构与算法知识,数据结构和算法告诉我们,对索引关键字进行快速查找时要使用树形数据结构,在数据库引擎中,索引通常用B+树来表示,google发现这方面的文章较少,后面找到相关详细资料会补充。

 

         4.主键、索引、聚集索引和非聚集索引

         1)主键   (PK)  

                唯一标识表中的所有行的一个列或一组列。主键不允许空值。不能存在具有相同的主键值的两个

         行,因此主键值总是唯一标识单个行。表中可以有不止一个键唯一标识行,每个键都称作候选键。只有

         一个候选键可以选作表的主键,所有其它候选键称作备用键。尽管表不要求具有主键,但定义主键是很

         好的做法。   在规范化的表中,每行中的所有数据值都完全依赖于主键。例如,在以   EmployeeID   作为

         主键的规范化的   employee   表中,所有列都应包含与某个特定职员相关的数据。该表不具有  

         DepartmentName 列,因为部门的名称依赖于部门   ID,而不是职员   ID。  

 

         2)索引  

               关系数据库中基于键值提供对表的行中数据的快速访问的数据库对象。索引还可以在表的行上强制唯

         一性。SQL   Server   支持聚集索引和非聚集索引。对表的主键自动进行索引。在全文搜索中,全文索引

         存储关于重要词和这些词在给定列中的位置的信息。  

               如果某列有多行包含   NULL   值,则不能在该列上创建唯一索引。同样,如果列的组合中有多行包

         含   NULL   值,则不能在多个列上创建唯一索引。在创建索引时,这些被视为重复的值。  

 

        3)聚集索引  

               在创建聚集索引时,将会对表进行复制,对表中的数据进行排序,然后删除原始的表。因此,数据库

         上必须有足够的空闲空间,以容纳数据复本。默认情况下,表中的数据在创建索引时排序。但是,如果

         因聚集索引已经存在,且正在使用同一名称和列重新创建,而数据已经排序,则会重建索引,而不是从

         头创建该索引,以自动跳过排序操作。重建操作会检查行是否在生成索引时进行了排序。如果有任何行

         排序不正确,即会取消操作,不创建索引。  

 

         4)非聚集索引  

               非聚集索引与课本中的索引类似。数据存储在一个地方,索引存储在另一个地方,索引带有指针指向

         数据的存储位置。索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存储(这可以由聚

         集索引规定)。如果在表中未创建聚集索引,则无法保证这些行具有任何特定的顺序。

 

         打开设计表界面里面有个钥匙就是主键的意思,当你声明一列为主键的时候数据库实际上就是生成一个

唯一的索引,查询优化器实际上是根据列上有没有唯一索引来保证列的唯一性而不是根据列是否被声明为主键。  

         聚集索引一个表只有一个,实际上它的叶子节点就是数据页,比非聚集索引速度快,占用的空间小,大概只有表的1%左右。如果在声明的时候没有选择UNIQUE选项,则在插入数据的时候会自动生成一个唯一标示符。  

         非聚集索引一个表可以有多个,一个3层的非聚簇索引要查询6次才可以找到真实数据,因为其叶子节点并不是真实数据,而是标识(如果表上有聚集索引则为聚集索引,如没有,则为实际数据的页号),非聚集索引通常占用空间比较大,表的30-40%。

 

 

 

 

 

Microsoft® SQL Server™ 2000 支持在表中任何列(包括计算列)上定义的索引。

 

如果一个表没有创建索引,则数据行不按任何特定的顺序存储。这种结构称为堆集。

 

SQL Server 索引的两种类型为:

 

聚集

聚集索引基于数据行的键值在表内排序和存储这些数据行。由于数据行按基于聚集索引键的排序次序存储,因此聚集索引对查找行很有效。每个表只能有一个聚集索引,因为数据行本身只能按一个顺序存储。数据行本身构成聚集索引的最低级别。

 

只有当表包含聚集索引时,表内的数据行才按排序次序存储。如果表没有聚集索引,则其数据行按堆集方式存储。

 

非聚集

非聚集索引具有完全独立于数据行的结构。非聚集索引的最低行包含非聚集索引的键值,并且每个键值项都有指针指向包含该键值的数据行。数据行不按基于非聚集键的次序存储。

 

在非聚集索引内,从索引行指向数据行的指针称为行定位器。行定位器的结构取决于数据页的存储方式是堆集还是聚集。对于堆集,行定位器是指向行的指针。对于有聚集索引的表,行定位器是聚集索引键。

 

只有在表上创建了聚集索引时,表内的行才按特定的顺序存储。这些行就基于聚集索引键按顺序存储。如果一个表只有非聚集索引,它的数据行将按无序的堆集方式存储。

 

索引可以是唯一的,这意味着不会有两行有相同的索引键值。另外,索引也可以不是唯一的,多个行可以共享同一键值。

 

有两种方法可以在 SQL Server 内定义索引。CREATE INDEX 语句创建并命名索引。CREATE TABLE 语句支持在创建索引时使用下列约束:

 

PRIMARY KEY 创建唯一索引来强制执行主键。

 

 

UNIQUE 创建唯一索引。

 

 

CLUSTERED 创建聚集索引。

 

 

NONCLUSTERED 创建非聚集索引。

当在 SQL Server 2000 上创建索引时,可指定是按升序还是降序存储键。

 

SQL Server 2000 支持在计算列上定义的索引,只要为列定义的表达式满足某些限制,如仅引用包含计算列的表中的列、具有确定性等。

 

填充因子是 SQL Server 索引的一个属性,它控制索引在创建时的填充密度。默认的填充因子通常能够提供较好的性能,但在某些情况下,更改填充因子可能会有益。如果打算对表执行许多更新和插入,则可在创建索引时使用小填充因子,以便为后面的键留出更多的空间。如果是不会更改的只读表,则可在创建索引时使用大填充因子,以减小索引的物理大小,这样可以降低 SQL Server 浏览索引时的磁盘读取次数。只有在创建索引时才能应用填充因子。随着键的插入和删除,索引最终将稳定在某个密度上。

 

索引不仅可以提高选择行的检索速度,通常还可以提高更新和删除的速度。这是因为 SQL Server 在更新或删除行时必须先找到该行。使用索引定位行提高了效率,这通常可以弥补更新索引所需的额外开销,除非表中有很多索引。

 

下例显示在表上创建索引的 Transact-SQL 语法。

 

USE pubs

GO

CREATE TABLE emp_sample

   (emp_id      int         PRIMARY KEY CLUSTERED,

   emp_name      char(50),

   emp_address   char(50),

   emp_title   char(25)      UNIQUE NONCLUSTERED )

GO

CREATE NONCLUSTERED INDEX sample_nonclust ON emp_sample(emp_name)

GO

 

对于具体什么样的索引集可优化性能这个问题,取决于系统中的查询混合。考察 emp_sample.emp_id 上的聚集索引。如果大多数引用 emp_sample 的查询在它们的 WHERE 子句中有关于 emp_id 的等式或范围比较,聚集索引将发挥很好的作用。如果大多数查询的 WHERE 子句引用的是 emp_name 而非 emp_id,则通过将 emp_name 上的索引置为聚集索引可提高性能。

 

许多应用程序的查询混合都很复杂,单靠询问用户和程序员很难进行评估。SQL Server 2000 提供索引优化向导,帮助您在数据库中设计索引。对具有复杂访问模式的大型架构,最简单的设计索引的方法是使用索引优化向导。

 

可以为索引优化向导提供一组 SQL 语句。这组语句可以是为反映系统中典型的语句混合而生成的语句脚本。不过,这组语句通常是 SQL 事件探查器跟踪记录,记录在系统典型负载期间系统上实际处理的 SQL 语句。索引优化向导分析工作负荷和数据库,然后提出可提高工作负荷性能的索引配置建议。可以选择替换现有的索引配置,或者保留现有的索引配置并实现新的索引,以提高执行速度慢的查询子集的性能。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  2、I/O吞吐量小,形成了瓶颈效应。

  

  3、没有创建计算列导致查询不优化。

 

computed_column_expression  

   

  是定义计算列值的表达式。计算列是物理上并不存储在表中的虚拟列。计算列由同一表中的其它列通过表达式计算得到。例如,计算列可以这样定义:cost   AS   price   *   qty。表达式可以是非计算列的列名、常量、函数、变量,也可以是用一个或多个运算符连接的上述元素的任意组合。表达式不能为子查询。  

   

  计算列可用于选择列表、WHERE   子句、ORDER   BY   子句或任何其它可使用常规表达式的位置,但下列情况除外:    

   

  计算列不能用作   DEFAULT   或   FOREIGN   KEY   约束定义,也不能与   NOT   NULL   约束定义一起使用。但是,如果计算列由具有确定性的表达式定义,并且索引列中允许计算结果的数据类型,则可将该列用作索引中的键列,或用作   PRIMARY   KEY   或   UNIQUE   约束的一部分。    

  例如,如果表中含有整型列   a   和   b,则可以在计算列   a+b   上创建索引。但不能在计算列   a+DATEPART(dd,   GETDATE())   上创建索引,因为在以后的调用中,其值可能发生改变。  

   

  计算列不能作为   INSERT   或   UPDATE   语句的目标。    

   

   

  说明     表中计算列所使用的列值因行而异,因此每行的计算列值可能不同。  

   

  计算列的为空性是由   SQL   Server   根据使用的表达式自动确定的。即使只有不可为空的列,大多数表达式的结果也认为是可为空的,因为可能的下溢或溢出也将生成   NULL   结果。使用   COLUMNPROPERTY   函数(AllowsNull   属性)查看表中任何计算列的为空性。通过指定   ISNULL(check_expression,   constant),其中常量为替代任何   NULL   结果的非   NULL   值,可为空的表达式   expr   可以转换为不可为空的表达式。

 

 

使用XML在SQL Server上创建计算列

 

 

 在SQL Server数据库中,当你想使用一个数据,而这个数据不保存在表中,计算列很有用。例如,你有一张表,它包括列dollar amounts, wholesale prices和retail prices。你肯定不想在每次查询表时来计算那两列之间的差值,你希望将其值保存在第三列中,让其自动计算前两列之间的差值。而此列就是计算列。

 

  在SQL Server中使用XML数据来创建计算列,你的列定义必须包含必要的用来检测向列中插入的是什么数据的表达式。例如,在上面的例子中,你的表达式应该从retail列中的值减去wholesale列中的值。当你添加或更新表中的数据行时,差值将自动插入至计算列中。

 

  你可以很容易地在两个或更多的包含字符串或数字类型值的列的基础上创建计算列。(更多关于如何创建此类型的计算列的详细信息,请参考Microsoft SQL Server Books Online)。然而,如果你想要基于指定的XML列中元素值创建一个计算列,该过程相对更加复杂一些。因为你必须使用Xquery表达式来从XML列中获取指定元素数据,且SQL Server不支持在计算列的定义中使用Xquery表达式。

 

  要解决此问题,可以创建一个函数来接收你想包含在计算列中的XML数据,并在计算列定义中调用此函数。更好的示范这是如何工作的,我们在这给出一个例子。我在SQL Server 2005的示例数据库AdventureWorks中创建以下的架构和表:

 

  USE AdventureWorks;

 

  GO

 

  CREATE SCHEMA hr

 

  GO

 

  SELECT TOP 10 JobCandidateID AS CandidateID,

 

  [Resume] AS JobResume

 

  INTO hr.CandidateNames

 

  FROM HumanResources.JobCandidate

 

  GO

  正如名称所示,HumanResources.JobCandidate表中的Resume列是一个XML列,它包含侯选人的履历信息。我从这张表中提取数据来创建hr架构中的CandidateNames表。(我创建了一个单独的表,因为我希望可以修改表定义,从而可以增加计算列) 在建立好测试环境后,你可以创建函数。函数应该包括在从指定的XML列中获取数据时所需的XQuery表达式。例如,以下函数接收工作候选人的姓名,并保存在JobResume列中:

 

  CREATE FUNCTION hr.FullName (@name XML)

 

  RETURNS NVARCHAR(60) AS

 

  BEGIN

 

  RETURN @name.value('declare namespace ns=

 

  "http://schemas.microsoft.com/sqlserver/2004/07/adventure-

 

  works/Resume";

 

  concat((/ns:Resume/ns:Name/ns:Name.First)[1], " ",

 

  (/ns:Resume/ns:Name/ns:Name.Last)[1])','nvarchar(60)')

 

  END

  正如你所看到的,函数FullName带一个输入参数,该参数被定义成XML类型。这个做法是当调用此函数时,可以把包含所需提取的数据的XML列名称作为输入值来使用。

 

  Value()方法带两个参数。第一个参数定义了目标XML列使用的名称空间,第二个参数包含接收实际数据的Xquery表达式。在这个例子中,表达式使用concat()方法来连接姓与名,就像它们在XML文件中。要想了解更多的关于如何使用value()方法,以及如何创建Xquery表达式,请查看我的文章《Retrieve XML data values with XQuery》。 一旦创建了函数,你可以通过从hr.CandidateNames表的JobResume列中接收数据测试:

 

  SELECT CandidateID, hr.FullName(JobResume) AS FullName FROM hr.CandidateNames

   正如你所看到的,我已经传入了XML列名称,将其做为函数FullName的一个参数。SELECT语句应该返回以下结果:

    CandidateID     FullName

    1           Shai Bassli

    2           Max Benson

    3           Krishna Sunkammurali

    4           Stephen Jiang

    5           Thierry D'Hers

    6           Christian Kleinerman

 

 

 

  注意,以上结果包含姓与名,正如它们在XML列中显示的一样。如果回到函数定义,可发现在value()方法中使用的Xquery表达式指定了此表达式返回值为NVARCHAR(60)类型,以适应Unicode字符,如查询结果集的最后三行中的那些字符。

 

  一旦函数经过测试,你就可以开始创建计算列:以下ALTER TABLE语句添加了FullName列到CandidateNames表中来:

 

  ALTER TABLE hr.CandidateNames

 

  ADD FullName AS hr.FullName(JobResume)

  我已经在计算列表达式中使用FullName函数,并将列JobResume作为参数传入函数。在运行ALTER TABLE语句后,你可以用以下SELECT语句测试数据是否已经被插入到计算列中:

 

  SELECT CandidateID, FullName FROM hr.CandidateNames

  运行以上语句后,应该返回与上文中相同的结果集。

 

  这就是在SQL Server中基于XML data数据创建的一个计算列。关键是创建一个函数来运行Xquery表达式,且稍后在计算列中使用此函数定义。要了解更多关于计算列、XML列、Xquery表达式的详细信息,请查看Microsoft SQL Server在线书籍。

 

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mazhaoyi/archive/2010/01/08/5158278.aspx

 

 

 

在CREATE TABLE或ALTER TABLE语句中定义的列可以源于独立的或者基于列的计算。如果需要在相关查询中对相同的数据重复计算,则计算列就变得很有用。计算列以创建表或修改表的时候定义的表达式为基础,除非使用了PERSISTED关键字,否则计算列不会物理保存在表中。

 

在这个技巧中,我会给出创建计算列的演示,并且介绍使用SQL Server 2005的PERSISTED选项的方法。通过CREATE或ALTER TABLE增加一个计算列的语法如下:

 

column_name AS computed_column_expression  [ PERSISTED ] column_name是新列的名字。computed_column_expression是你为了得到列的值而执行的计算。增加PERSISTED关键字能让计算的结果被物理保存。

 

在这个示例中,我们向既有表中加了一个新的计算列:

 

ALTER TABLE Production.TransactionHistory  ADD CostPerUnit AS (ActualCost/Quantity) 前面的示例创建了一个名为CostPerUnit的计算列。下一个查询利用它返回数量超过10的最高的CostPerUnit:

 

SELECT TOP 1 CostPerUnit, Quantity, ActualCost  FROM Production.TransactionHistory  WHERE Quantity > 10 ORDER BY ActualCost DESC 这个查询返回:

 

CostPerUnit    Quantity    ActualCost  132.0408       13          1716.5304 下一个示例创建一个PERSISTED计算列,这意味着计算后的数据实际上会物理地保存在数据库中(但仍然是由SQL Server自动计算):

 

CREATE TABLE HumanResources.CompanyStatistic   (CompanyID int NOT NULL,   StockTicker char(4) NOT NULL,   SharesOutstanding int NOT NULL,   Shareholders int NOT NULL,   AvgSharesPerShareholder AS (SharesOutStanding/Shareholders) PERSISTED) 解析

 

第一个示例向Production.TransactionHistory表添加了一个名为CostPerUnit的非持久化列,使它在SELECT查询中能像普通表列那样被引用:

 

ADD CostPerUnit AS (ActualCost/Quantity) 计算列不能用DEFAULT或者FOREIGN KEY约束。计算列不能被显式更新或插入(因为它的值都是计算出的)。

 

计算列能用在索引中,但是一定要符合一些条件。比如是确定的(对于一组给定的输入总是返回相同的结果)和精确的(不包含浮点值)。

 

第二个示例演示了在CREATE TABLE命令中使用计算列:

 

AvgSharesPerShareholder AS (SharesOutStanding/Shareholders) PERSISTED 和第一个示例不同,增加了PERSISTED意味着数据被物理地保存在数据库中。对计算中使用的列进行的任何修改都会引起存储值的再一次更新。但是保存的数据仍然不可以直接修改--数据仍然要经过计算。然而和非持久化的方式不同,保存数据意味着列能用于表分区(请参阅4.7.1节的"实现表分区"技巧)或者非精确(基于浮点)值的索引。

 

 

 

 

 

 

  

  4、内存不足

  

  5、网络速度慢

  

  6、查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)

  

  7、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)

  

 

  【IT专家网独家】死锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用下,它们都将无法推进下去,死时就可能会产生死锁,这些永远在互相等待的进程称为死锁线程。简单的说,进程A等待进程B释放他的资源,B又等待A释放他的资源,这样互相等待就形成死锁。

 

  如在数据库中,如果需要对一条数据进行修改,首先数据库管理系统会在上面加锁,以保证在同一时间只有一个事务能进行修改操作。如事务1的线程 T1具有表A上的排它锁,事务2的线程T2 具有表B上的排它锁,并且之后需要表A上的锁。事务2无法获得这一锁,因为事务1已拥有它。事务2被阻塞,等待事务1。然后,事务1需要表B的锁,但无法获得锁,因为事务2将它锁定了。事务在提交或回滚之前不能释放持有的锁。因为事务需要对方控制的锁才能继续操作,所以它们不能提交或回滚,这样数据库就会发生死锁了。

 

  如在编写存储过程的时候,由于有些存储过程事务性的操作比较频繁,如果先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。如果无意中某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。而且死锁一般是不太容易被发现的。

 

  如果服务器上经常出现这种死锁情况,就会降低服务器的性能,所以应用程序在使用的时候,我们就需要对其进行跟踪,使用sp_who和sp_who2来确定可能是哪些用户阻塞了其他用户,我们还可以用下面的存储过程来跟踪具体的死锁执行的影响:

 

create  procedure sp_who_lock

as

begin

declare @spid int,@bl int,

        @intTransactionCountOnEntry  int,

        @intRowcount    int,

        @intCountProperties   int,

        @intCounter    int

 create table #tmp_lock_who (id int identity(1,1),spid smallint,bl smallint)

 

 IF @@ERROR<>0 RETURN @@ERROR

 

 insert into #tmp_lock_who(spid,bl) select  0 ,blocked

   from (select * from sysprocesses where  blocked>0 ) a

   where not exists(select * from (select * from sysprocesses where  blocked>0 ) b

   where a.blocked=spid)

   union select spid,blocked from sysprocesses where  blocked>0

 

 IF @@ERROR<>0 RETURN @@ERROR

 

-- 找到临时表的记录数

 select  @intCountProperties = Count(*),@intCounter = 1

 from #tmp_lock_who

 

 IF @@ERROR<>0 RETURN @@ERROR

 

 if @intCountProperties=0

  select '现在没有阻塞和死锁信息' as message

 

-- 循环开始

while @intCounter <= @intCountProperties

begin

-- 取第一条记录

  select  @spid = spid,@bl = bl

  from #tmp_lock_who where id = @intCounter

 begin

  if @spid =0

    select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'

 else

    select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'

 DBCC INPUTBUFFER (@bl )

 end

 

-- 循环指针下移

 set @intCounter = @intCounter + 1

end

 

 

drop table #tmp_lock_who

 

return 0

end

 

  我们只需要通过在查询分析器里面执行sp_who_lock,就可以具体捕捉到执行的堵塞进程,这时我们就可以对对应的SQL语句或者存储过程进行性能上面的改进及设计。

 

  所以我们在数据库设计的时候,虽然不能完全避免死锁,但可以使死锁的数量尽量减少。增加事务的吞吐量并减少系统开销,因为只有很少的事务,所以就得遵循下面的原则:

 

  按同一顺序访问对象

 

  如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。在写SQL语句或存储过程的时候,就需要按照顺序在两个并发事务中先获得表A上的锁,然后获得表B上的锁,当第一个事务完成之前,另一个事务被阻塞在表A上。第一个事务提交或回滚后,第二个事务继续进行,而不能在语句里面写先获得表B上的锁,然后再获得表A的锁。

 

  避免事务中的用户交互

 

  避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户就去做别的事了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。

 

  保持事务简短并在一个批处理中

 

  在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

 

  使用低隔离级别

 

  确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。

 

  使用绑定连接

 

  使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。

 

  下面有一些对死锁发生的一些建议:

 

  1)对于频繁使用的表使用集簇化的索引;

 

  2)设法避免一次性影响大量记录的T-SQL语句,特别是INSERT和UPDATE语句;

 

  3)设法让UPDATE和DELETE语句使用索引;

 

  4)使用嵌套事务时,避免提交和回退冲突;

 

  5)对一些数据不需要及时读取更新值的表在写SQL的时候在表后台加上(nolock),如:Select * from tableA(nolock)

  假如发生了死锁,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程?此时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。

 

 

  use master

  go

  create procedure sp_who_lock

  as

  begin

  declare @spid int,@bl int,

  @intTransactionCountOnEntry int,

  @intRowcount int,

  @intCountProperties int,

  @intCounter int

  create table #tmp_lock_who (

  id int identity(1,1),

  spid smallint,

  bl smallint)

  IF @@ERROR<>0 RETURN @@ERROR

  insert into #tmp_lock_who(spid,bl) select 0 ,blocked

  from (select * from sysprocesses where blocked>0 ) a

  where not exists(select * from

  (select * from sysprocesses where blocked>0 ) b

  where a.blocked=spid)

  union select spid,blocked from sysprocesses where blocked>0

  IF @@ERROR<>0 RETURN @@ERROR

  -- 找到临时表的记录数

  select @intCountProperties = Count(*),@intCounter = 1

  from #tmp_lock_who

  IF @@ERROR<>0 RETURN @@ERROR

  if @intCountProperties=0

  select '现在没有阻塞和死锁信息' as message

  -- 循环开始

  while @intCounter <= @intCountProperties

  begin

  -- 取第一条记录

  select @spid = spid,@bl = bl

  from #tmp_lock_who where Id = @intCounter

  begin

  if @spid =0

  select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10))

  + '进程号,其执行的SQL语法如下'

  else

  select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被'

  + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当

  前进程执行的SQL语法如下'DBCC INPUTBUFFER

 

SQL SERVER 查看和杀掉死锁的进程代码

 

 set ANSI_NULLS ON 防黑网.www.zzfhw.com

set QUOTED_IDENTIFIER ON 防黑网.www.zzfhw.com

go 防黑网.www.zzfhw.com

 防黑网.www.zzfhw.com

     防黑网.www.zzfhw.com

  /**//*--调用示例    防黑网.www.zzfhw.com

     防黑网.www.zzfhw.com

  exec   p_lockinfo 0,1   防黑网.www.zzfhw.com

  --*/    防黑网.www.zzfhw.com

  CREATE proc   [dbo].[p_lockinfo]    防黑网.www.zzfhw.com

  @kill_lock_spid   bit=1, --是否杀掉死锁的进程,1   杀掉,   0   仅显示    防黑网.www.zzfhw.com

  @show_spid_if_nolock   bit=1 --如果没有死锁的进程,是否显示正常进程信息,1   显示,0   不显示    防黑网.www.zzfhw.com

  as    防黑网.www.zzfhw.com

  set   nocount   on    防黑网.www.zzfhw.com

  declare   @count   int,@s   nvarchar(1000),@i   int    防黑网.www.zzfhw.com

  select   id=identity(int,1,1),标志,    防黑网.www.zzfhw.com

  进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid,    防黑网.www.zzfhw.com

  数据库名=db_name(dbid),用户ID=uid,用户名=loginame,累计CPU时间=cpu,    防黑网.www.zzfhw.com

  登陆时间=login_time,打开事务数=open_tran, 进程状态=status,    防黑网.www.zzfhw.com

  工作站名=hostname,应用程序名=program_name,工作站进程ID=hostprocess,    防黑网.www.zzfhw.com

  域名=nt_domain,网卡地址=net_address    防黑网.www.zzfhw.com

  into   #t   from(    防黑网.www.zzfhw.com

  select   标志='死锁的进程',    防黑网.www.zzfhw.com

  spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,    防黑网.www.zzfhw.com

  status,hostname,program_name,hostprocess,nt_domain,net_address,    防黑网.www.zzfhw.com

  s1=a.spid,s2=0    防黑网.www.zzfhw.com

  from   master..sysprocesses   a   join   (    防黑网.www.zzfhw.com

  select   blocked   from   master..sysprocesses   group   by   blocked    防黑网.www.zzfhw.com

  )b   on   a.spid=b.blocked   where   a.blocked=0    防黑网.www.zzfhw.com

  union   all    防黑网.www.zzfhw.com

  select   '|_牺牲品_>',    防黑网.www.zzfhw.com

  spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,    防黑网.www.zzfhw.com

  status,hostname,program_name,hostprocess,nt_domain,net_address,    防黑网.www.zzfhw.com

  s1=blocked,s2=1    防黑网.www.zzfhw.com

  from   master..sysprocesses   a   where   blocked<>0    防黑网.www.zzfhw.com

  )a   order   by   s1,s2    防黑网.www.zzfhw.com

     防黑网.www.zzfhw.com

  select   @count=@@rowcount,@i=1    防黑网.www.zzfhw.com

     防黑网.www.zzfhw.com

  if   @count=0   and   @show_spid_if_nolock=1    防黑网.www.zzfhw.com

  begin    防黑网.www.zzfhw.com

  insert   #t    防黑网.www.zzfhw.com

  select   标志='正常的进程',    防黑网.www.zzfhw.com

  spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,    防黑网.www.zzfhw.com

  open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address    防黑网.www.zzfhw.com

  from   master..sysprocesses    防黑网.www.zzfhw.com

  set   @count=@@rowcount    防黑网.www.zzfhw.com

  end    防黑网.www.zzfhw.com

     防黑网.www.zzfhw.com

  if   @count>0    防黑网.www.zzfhw.com

  begin    防黑网.www.zzfhw.com

  create   table   #t1(id   int   identity(1,1),a   nvarchar(30),b   Int,EventInfo   nvarchar(255))    防黑网.www.zzfhw.com

  if   @kill_lock_spid=1    防黑网.www.zzfhw.com

  begin    防黑网.www.zzfhw.com

  declare   @spid   varchar(10),@标志   varchar(10)    防黑网.www.zzfhw.com

  while   @i<=@count    防黑网.www.zzfhw.com

  begin    防黑网.www.zzfhw.com

  select   @spid=进程ID,@标志=标志   from   #t   where   id=@i    防黑网.www.zzfhw.com

  insert   #t1   exec('dbcc   inputbuffer('+@spid+')')    防黑网.www.zzfhw.com

  if   @@rowcount=0   insert   #t1(a)   values(null)    防黑网.www.zzfhw.com

  if   @标志='死锁的进程'   exec('kill   '+@spid)    防黑网.www.zzfhw.com

  set   @i=@i+1    防黑网.www.zzfhw.com

  end    防黑网.www.zzfhw.com

  end    防黑网.www.zzfhw.com

  else    防黑网.www.zzfhw.com

  while   @i<=@count    防黑网.www.zzfhw.com

  begin    防黑网.www.zzfhw.com

  select   @s='dbcc   inputbuffer('+cast(进程ID   as   varchar)+')'   from   #t   where   id=@i    防黑网.www.zzfhw.com

  insert   #t1   exec(@s)    防黑网.www.zzfhw.com

  if   @@rowcount=0   insert   #t1(a)   values(null)    防黑网.www.zzfhw.com

  set   @i=@i+1    防黑网.www.zzfhw.com

  end    防黑网.www.zzfhw.com

  select   a.*,进程的SQL语句=b.EventInfo    防黑网.www.zzfhw.com

  from   #t   a   join   #t1   b   on   a.id=b.id    防黑网.www.zzfhw.com

  order   by   进程ID    防黑网.www.zzfhw.com

  end    防黑网.www.zzfhw.com

  set   nocount   off 

 

 

如何减少SQL Server死锁发生的情况

 

死锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用下,它们都将无法推进下去,死时就可能会产生死锁,这些永远在互相等待的进程称为死锁线程。简单的说,进程A等待进程B释放他的资源,B又等待A释放他的资源,这样互相等待就形成死锁。

 

如在数据库中,如果需要对一条数据进行修改,首先数据库管理系统会在上面加锁,以保证在同一时间只有一个事务能进行修改操作。如事务1的线程 T1具有表A上的排它锁,事务2的线程T2 具有表B上的排它锁,并且之后需要表A上的锁。事务2无法获得这一锁,因为事务1已拥有它。事务2被阻塞,等待事务1。然后,事务1需要表B的锁,但无法获得锁,因为事务2将它锁定了。事务在提交或回滚之前不能释放持有的锁。因为事务需要对方控制的锁才能继续操作,所以它们不能提交或回滚,这样数据库就会发生死锁了。

 

如在编写存储过程的时候,由于有些存储过程事务性的操作比较频繁,如果先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。如果无意中某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。而且死锁一般是不太容易被发现的。

 

如果服务器上经常出现这种死锁情况,就会降低服务器的性能,所以应用程序在使用的时候,我们就需要对其进行跟踪,使用sp_who和sp_who2来确定可能是哪些用户阻塞了其他用户,我们还可以用下面的存储过程来跟踪具体的死锁执行的影响:

 

create procedure sp_who_lockasbegindeclare @spid int,@bl int,@intTransactionCountOnEntry int,@intRowcount int,@intCountProperties int,@intCounter int create table #tmp_lock_who (id int identity(1,1),spid smallint,bl smallint)IF @@ERROR<>0 RETURN @@ERRORinsert into #tmp_lock_who(spid,bl) select 0 ,blockedfrom (select * from sysprocesses where blocked>0 ) a where not exists(select * from (select * from sysprocesses where blocked>0 ) b where a.blocked=spid)union select spid,blocked from sysprocesses where blocked>0IF @@ERROR<>0 RETURN @@ERROR -- 找到临时表的记录数select @intCountProperties = Count(*),@intCounter = 1from #tmp_lock_whoIF @@ERROR<>0 RETURN @@ERROR if @intCountProperties=0select '现在没有阻塞和死锁信息' as message-- 循环开始while @intCounter <= @intCountPropertiesbegin-- 取第一条记录select @spid = spid,@bl = blfrom #tmp_lock_who where id = @intCounter beginif @spid =0 select '引起数据库死锁的是: ' CAST(@bl AS VARCHAR(10)) '进程号,其执行的SQL语法如下'elseselect '进程号SPID:' CAST(@spid AS VARCHAR(10)) '被' '进程号SPID:' CAST(@bl AS VARCHAR(10)) '阻塞,其当前进程执行的SQL语法如下'DBCC INPUTBUFFER (@bl )end -- 循环指针下移set @intCounter = @intCounter 1enddrop table #tmp_lock_whoreturn 0

 

我们只需要通过在查询分析器里面执行sp_who_lock,就可以具体捕捉到执行的堵塞进程,这时我们就可以对对应的SQL语句或者存储过程进行性能上面的改进及设计。

 

所以我们在数据库设计的时候,虽然不能完全避免死锁,但可以使死锁的数量尽量减少。增加事务的吞吐量并减少系统开销,因为只有很少的事务,所以就得遵循下面的原则:

 

按同一顺序访问对象

 

如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。在写SQL语句或存储过程的时候,就需要按照顺序在两个并发事务中先获得表A上的锁,然后获得表B上的锁,当第一个事务完成之前,另一个事务被阻塞在表A上。第一个事务提交或回滚后,第二个事务继续进行,而不能在语句里面写先获得表B上的锁,然后再获得表A的锁。

 

避免事务中的用户交互

 

避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户就去做别的事了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。

 

保持事务简短并在一个批处理中

 

在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

 

使用低隔离级别

 

确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。

 

使用绑定连接

 

使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。

 

下面有一些对死锁发生的一些建议:

 

1)对于频繁使用的表使用集簇化的索引;

 

2)设法避免一次性影响大量记录的T-SQL语句,特别是INSERT和UPDATE语句;

 

3)设法让UPDATE和DELETE语句使用索引;

 

4)使用嵌套事务时,避免提交和回退冲突;

 

5)对一些数据不需要及时读取更新值的表在写SQL的时候在表后台加上(nolock),如:Select * from tableA(nolock)

 

 

sql server死锁的问题

 

常看到死锁的问题,一般都是KILL进程,但如果不查出引起死锁的原因,死锁会时常发生

可以通过查找引起死锁的的操作,就可以方便的解决死锁,现将日常解决问题的方法总结,也许对大家有帮助

 

1\死锁发生时,通过如下语法,查询出引起死锁的操作

 

use master

go

declare @spid int,@bl int

DECLARE s_cur CURSOR FOR 

select  0 ,blocked

from (select * from sysprocesses where  blocked>0 ) a 

where not exists(select * from (select * from sysprocesses where  blocked>0 ) b 

where a.blocked=spid)

union select spid,blocked from sysprocesses where  blocked>0

OPEN s_cur

FETCH NEXT FROM s_cur INTO @spid,@bl

WHILE @@FETCH_STATUS = 0

begin

if @spid =0 

            select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'

else

            select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'

DBCC INPUTBUFFER (@bl )

FETCH NEXT FROM s_cur INTO @spid,@bl

end

CLOSE s_cur

DEALLOCATE s_cur

 

exec sp_who2

2\查找程序/数据库,此t_sql语法在什么地方使用

3\分析找到的,并解决问题

 

EG:

 

/*

------------------------------------------------------- 

引起数据库死锁的是: 71进程号,其执行的SQL语法如下

 

EventType      Parameters EventInfo                                        

-------------- ---------- ------------------------------------------------ 

Language Event 0          

select * from test

insert test values(1,2)

 

 

(所影响的行数为 1 行)

 

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

                                                                               

------------------------------------------------------------------------------ 

进程号SPID:64被进程号SPID:71阻塞,其当前进程执行的SQL语法如下

 

EventType      Parameters EventInfo                                        

-------------- ---------- ------------------------------------------------ 

Language Event 0          

select * from test

insert test values(1,2)

 

 

(所影响的行数为 1 行)

 

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

                                                                               

------------------------------------------------------------------------------ 

进程号SPID:65被进程号SPID:64阻塞,其当前进程执行的SQL语法如下

 

EventType      Parameters EventInfo                                                                                          

-------------- ---------- -------------------------------------------------------------------------------------------------- 

Language Event 0          begin tran

select * from test with (holdlock)

waitfor time '12:00'

select * from test

commit

 

(所影响的行数为 1 行)

 

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

                                                                                

------------------------------------------------------------------------------ 

进程号SPID:73被进程号SPID:64阻塞,其当前进程执行的SQL语法如下

 

EventType      Parameters EventInfo                                                                                           

-------------- ---------- -------------------------------------------------------------------------------------------------- 

Language Event 0          begin tran

select * from test with (holdlock)

waitfor time '12:00'

select * from test

commit

 

(所影响的行数为 1 行)

 

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

*/

 

0 顶一下

 

 

 

 

 

 

 

 

 

 

 

  8、sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。

  

  9、返回了不必要的行和列

  

  10、查询语句不好,没有优化

 

  可以通过如下方法来优化查询 :

  

  1、把数据、日志、索引放到不同的I/O设备上,增加读取速度,以前可以将Tempdb应放在RAID0上,SQL2000不在支持。数据量(尺寸)越大,提高I/O越重要.

  

  2、纵向、横向分割表,减少表的尺寸(sp_spaceuse)

  

  3、升级硬件

  

  4、根据查询条件,建立索引,优化索引、优化访问方式,限制结果集的数据量。注意填充因子要适当(最好是使用默认值0)。索引应该尽量小,使用字节数小的列建索引好(参照索引的创建),不要对有限的几个值的字段建单一索引如性别字段

  

  5、提高网速;

  

  6、扩大服务器的内存,Windows 2000和SQL server 2000能支持4-8G的内存。配置虚拟内存:虚拟内存大小应基于计算机上并发运行的服务进行配置。运行 Microsoft SQL Server? 2000 时,可考虑将虚拟内存大小设置为计算机中安装的物理内存的 1.5 倍。如果另外安装了全文检索功能,并打算运行 Microsoft 搜索服务以便执行全文索引和查询,可考虑:将虚拟内存大小配置为至少是计算机中安装的物理内存的 3 倍。将 SQL Server max  server memory 服务器配置选项配置为物理内存的 1.5 倍(虚拟内存大小设置的一半)。

  

  7、增加服务器 CPU个数;但是必须明白并行处理串行处理更需要资源例如内存。使用并行还是串行程是MsSQL自动评估选择的。单个任务分解成多个任务,就可以在处理器上运行。例如耽搁查询的排序、连接、扫描和GROUP BY字句同时执行,SQL SERVER根据系统的负载情况决定最优的并行等级 ,复杂的需要消耗大量的CPU的查询最适合并行处理。但是更新操作Update,Insert, Delete还不能并行处理。

  

  8、如果是使用like进行查询的话,简单的使用index是不行的,但是全文索引,耗空间。 like 'a%' 使用索引 like '%a' 不使用索引用 like  '%a%' 查询时,查询耗时和字段值总长度成正比,所以不能用CHAR类型,而是VARCHAR。对于字段的值很长的 建全文索引。

  

  9、DB Server 和APPLication Server 分离;OLTP和OLAP分离

  

  10、分布式分区视图可用于实现数据库服务器联合体。联合体是一组分开管理的服务器,但它们相互协作分担系统的处理负荷。这种通过分区数据形成数据库服务器联合体的机制能够扩大一组服务器,以支持大型的多层 Web 站点的处理需要。有关更多信息,参见设计联合数据库服务器。(参 照SQL帮助文件'分区视图')

  

  a、在实现分区视图之前,必须先水平分区表

  

  b、在创建成员表后,在每个成员服务器上定义一个分布式分区视图,并且每个视图具有相同的名称。这样,引用分布式分区视图名的查询可以在任何一个成员服务器上运行。系统操作如同每个成员服务器上都有一个原始表的复本一样,但其实每个服务器上只有一个成员表和一个分布式分区视 图。数据的位置对应用程序是透明的。

  

  11、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收缩数据和日志 DBCC SHRINKDB,DBCC SHRINKFILE. 设置自动收缩日志.对于大的数据库不要设 置数据库自动增长,它会降低服务器的性能。在T-sql的写法上有很大的讲究,下面列出常见的要点:首先,DBMS处理查询计划的过程是这样的:

  

  1、 查询语句的词法、语法检查

  

  2、 将语句提交给DBMS的查询优化器

  

  3、 优化器做代数优化和存取路径的优化

  

  4、 由预编译模块生成查询规划

  

  5、 然后在合适的时间提交给系统处理执行

  

  6、 最后将执行结果返回给用户其次,看一下SQL SERVER的数据存放的结构:一个页面的大小为8K(8060)字节,8个页面为一个盘区,按照B树存放。

  

  12、Commit和rollback的区别 Rollback:回滚所有的事物。 Commit:提交当前的事物. 没有必要在动态SQL里写事物,如果要写请写在外面如:  begin tran exec(@s) commit trans 或者将动态SQL 写成函数或者存储过程。

  

  13、在查询Select语句中用Where字句限制返回的行数,避免表扫描,如果返回不必要的数据,浪费了服务器的I/O资源,加重了网络的负担降低性能。如果表很大,在表扫描的期间将表锁住,禁止其他的联接访问表,后果严重。

  

  14、SQL的注释申明对执行没有任何影响

  15、尽可能不使用光标,它占用大量的资源。如果需要row-by-row地执行,尽量采用非光标技术,如:在客户端循环,用临时表,Table变量,用子查询,用Case语句等等。游标可以按照它所支持的提取选项进行分类: 只进 必须按照从第一行到最后一行的顺序提取行。FETCH NEXT 是唯一允许 的提取操作,也是默认方式。可滚动性可以在游标中任何地方随机提取任意行。游标的技术在SQL2000下变得功能很强大,他的目的是支持循环。有四个并发选项 READ_ONLY:不允许通过游标定位更新(Update),且在组成结果集的行中没有锁。 OPTIMISTIC WITH valueS:乐观并发控制是事务控制理论的一个标准部分。乐观并发控制用于这样的情形,即在打开游标及更新行的间隔中,只有很小的机会让第二个用户更新某一行。当某个游标以此选 项打开时,没有锁控制其中的行,这将有助于最大化其处理能力。如果用户试图修改某一行,则此行的当前值会与最后一次提取此行时获取的值进行比较。如果任何值发生改变,则服务器就会知道其他人已更新了此行,并会返回一个错误。如果值是一样的,服务器就执行修改。选择这个并发选项 OPTIMISTIC WITH ROW VERSIONING:此乐观并发控制选项基于行版本控制。使用行版本控制,其中的表必须具有某种版本标识符,服务器可用它来确 定该行在读入游标后是否有所更改。在 SQL Server 中,这个性能由 timestamp 数据类型提供,它是一个二进制数字,表示数据库中更改的相对顺序 。每个数据库都有一个全局当前时间戳值:@@DBTS。每次以任何方式更改带有 timestamp 列的行时,SQL Server 先在时间戳列中存储当前的 @@DBTS  值,然后增加 @@DBTS 的值。如果某 个表具有 timestamp 列,则时间戳会被记到行级。服务器就可以比较某行的当前时间戳值和上次提取时所存储的时间戳值,从而确定该行是否已更新。服务器不必比较所有列的值,只需比较 timestamp 列即可。如果应用程序对没有 timestamp 列的表要求基 于行版本控制的乐观并发,则游标默认为基于数值的乐观并发控制。 SCROLL LOCKS 这个选项实现悲观并发控制。在悲观并发控制中,在把数据库的 行读入游标结果集时,应用程序将试图锁定数据库行。在使用服务器游标时,将行读入游标时会在其上放置一个更新锁。如果在事务内打开游标,则该事务更新锁将一直保持到事务被提交或回滚;当提取下一行时,将除去游标锁。如果在事务外打开游标,则提取下一行时,锁就被丢弃。因此,每 当用户需要完全的悲观并发控制时,游标都应在事务内打开。更新锁将阻止任何其它任务获取更新锁或排它锁,从而阻止其它任务更新该行。然而,更新锁并不阻止共享锁,所以它不会阻止其它任务读取行,除非第二个任务也在要求带更新锁的读取。滚动锁根据在游标定义的 Select 语句中指定 的锁提示,这些游标并发选项可以生成滚动锁。滚动锁在提取时在每行上获取,并保持到下次提取或者游标关闭,以先发生者为准。下次提取时,服务器为新提取中的行获取滚动锁,并释放上次提取中行的滚动锁。滚动锁独立于事务锁,并可以保持到一个提交或回滚操作之后。如果提交时关闭游 标的选项为关,则 COMMIT 语句并不关闭任何打开的游标,而且滚动锁被保留到提交之后,以维护对所提取数据的隔离。所获取滚动锁的类型取决于 游标并发选项和游标 Select 语句中的锁提示。锁提示只读 乐观数值 乐观行版本控制 锁定无提示 未锁定 未锁定 未锁定 更新 NOLOCK 未锁定 未 锁定未锁定 未锁定 HOLDLOCK 共享 共享 共享 更新 UPDLOCK 错误 更新 更新 更新 TABLOCKX 错误 未锁定 未锁定更新其它 未锁定 未锁定 未锁定  更新 *指定 NOLOCK 提示将使指定了该提示的表在游标内是只读的。

  

  16、用Profiler来跟踪查询,得到查询所需的时间,找出SQL的问题所在;用索引优化器优化索引

  

  17、注意UNion和UNion all 的区别。UNION all好

  

  18、注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的

  

  19、查询时不要返回不需要的行、列

  

  20、用sp_configure 'query governor cost limit'或者SET QUERY_GOVERNOR_COST_LIMIT来限制查询消耗的资源。当评估查询消耗的资源超出限 制时,服务器自动取消查询,在查询之前就扼杀掉。 SET LOCKTIME设置锁的时间

  

  21、用select top 100 / 10 Percent 来限制用户返回的行数或者SET ROWCOUNT来限制操作的行

  

  22、在SQL2000以前,一般不要用如下的字句: "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", and  "LIKE '%500'",因为他们不走索引全是表扫描。也不要在Where字句中的列名加函数,如Convert,substring等,如果必须用函数的时候,创建计算列再创建索引来替代.还可以变通写法:Where SUBSTRING(firstname,1,1) = 'm'改为Where firstname like 'm%'(索引扫描),一定要将函数和列名 分开。并且索引不能建得太多和太大。NOT IN会多次扫描表,使用EXISTS、NOT EXISTS ,IN , LEFT OUTER JOIN 来替代,特别是左连接,而Exists比 IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,现在2000的优化器能够处理了。相同的是IS NULL,"NOT", "NOT EXISTS",  "NOT IN"能优化她,而"<>"等还是不能优化,用不到索引。

  

  23、使用Query Analyzer,查看SQL语句的查询计划和评估分析是否是优化的SQL。一般的20%的代码占据了80%的资源,我们优化的重点是这些慢的地方。

  

  24、如果使用了IN或者OR等时发现查询没有走索引,使用显示申明指定索引: Select * FROM PersonMember (INDEX = IX_Title) Where  processid IN ('男','女')

  

  25、将需要查询的结果预先计算好放在表中,查询的时候再Select。这在SQL7.0以前是最重要的手段。例如医院的住院费计算。

  

  26、MIN() 和 MAX()能使用到合适的索引。

  

  27、数据库有一个原则是代码离数据越近越好,所以优先选择Default,依次为Rules,Triggers, Constraint(约束如外健主健CheckUNIQUE……, 数据类型的最大长度等等都是约束),Procedure.这样不仅维护工作小,编写程序质量高,并且执行的速度快。

  

  28、如果要插入大的二进制值到Image列,使用存储过程,千万不要用内嵌Insert来插入(不知JAVA是否)。因为这样应用程序首先将二进制值转换成字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值.存储过程就没有这些动作: 方法:Create procedure p_insert as insert  into table(Fimage) values (@image), 在前台调用这个存储过程传入二进制参数,这样处理速度明显改善。

  

  29、Between在某些时候比IN 速度更快,Between能够更快地根据索引找到范围。用查询优化器可见到差别。 select * from chineseresume  where title in ('男','女') Select * from chineseresume where between '男' and '女' 是一样的。由于in会在比较多次,所以有时会慢些。

  

  30、在必要是对全局或者局部临时表创建索引,有时能够提高速度,但不是一定会这样,因为索引也耗费大量的资源。他的创建同是实际表一样。

  

  31、不要建没有作用的事物例如产生报表时,浪费资源。只有在必要使用事物时使用它。

  

  32、用OR的字句可以分解成多个查询,并且通过UNION 连接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用UNION  all执行的效率更高.多个OR的字句没有用到索引,改写成UNION的形式再试图与索引匹配。一个关键的问题是否用到索引。

  

   33、尽量少用视图,它的效率低。对视图操作比直接对表操作慢,可以用stored procedure来代替她。特别的是不要用视图嵌套,嵌套视图增加了 寻找原始资料的难度。我们看视图的本质:它是存放在服务器上的被优化好了的已经产生了查询规划的SQL。对单个表检索数据时,不要使用指向多个表的视图,直接从表检索或者仅仅包含这个表的视图上读,否则增加了不必要的开销,查询受到干扰.为了加快视图的查询,MsSQL增加了视图索引的功 能。

  

  34、没有必要时不要用DISTINCT和ORDER BY,这些动作可以改在客户端执行。它们增加了额外的开销。这同UNION 和UNION ALL一样的道理。

  

  select top 20 ad.companyname,comid,position,ad.referenceid,worklocation, convert(varchar(10),ad.postDate,120) as  postDate1,workyear,degreedescription FROM jobcn_query.dbo.COMPANYAD_query ad where referenceID in ('JCNAD00329667','JCNAD132168','JCNAD00337748','JCNAD00338345',

  'JCNAD00333138','JCNAD00303570','JCNAD00303569',

  'JCNAD00303568','JCNAD00306698','JCNAD00231935','JCNAD00231933',

  'JCNAD00254567','JCNAD00254585','JCNAD00254608',

  'JCNAD00254607','JCNAD00258524','JCNAD00332133','JCNAD00268618',

  'JCNAD00279196','JCNAD00268613') order by postdate desc

  

  35、在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数。

  

  36、当用Select INTO时,它会锁住系统表(sysobjects,sysindexes等等),阻塞其他的连接的存取。创建临时表时用显示申明语句,而不是  select INTO. drop table t_lxh begin tran select * into t_lxh from chineseresume where name = 'XYZ' --commit 在另一个连接中Select *  from sysobjects可以看到 Select INTO 会锁住系统表,Create table 也会锁系统表(不管是临时表还是系统表)。所以千万不要在事物内使用它!! !这样的话如果是经常要用的临时表请使用实表,或者临时表变量。

  

  37、一般在GROUP BY 个HAVING字句之前就能剔除多余的行,所以尽量不要用它们来做剔除行的工作。他们的执行顺序应该如下最优:select 的 Where字句选择所有合适的行,Group By用来分组个统计行,Having字句用来剔除多余的分组。这样Group By 个Having的开销小,查询快.对于大的数据行进行分组和Having十分消耗资源。如果Group BY的目的不包括计算,只是分组,那么用Distinct更快

  

  38、一次更新多条记录比分多次更新每次一条快,就是说批处理好

  

  39、少用临时表,尽量用结果集和Table类性的变量来代替它,Table 类型的变量比临时表好

  

  40、在SQL2000下,计算字段是可以索引的,需要满足的条件如下:

  

  a、计算字段的表达是确定的

  

  b、不能用在TEXT,Ntext,Image数据类型

  

  c、必须配制如下选项 ANSI_NULLS = ON, ANSI_PADDINGS = ON, …….

  

  41、尽量将数据的处理工作放在服务器上,减少网络的开销,如使用存储过程。存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中的SQL语句,是控制流语言的集合,速度当然快。反复执行的动态SQL,可以使用临时存储过程,该过程(临时表)被放在Tempdb中。以 前由于SQL SERVER对复杂的数学计算不支持,所以不得不将这个工作放在其他的层上而增加网络的开销。SQL2000支持UDFs,现在支持复杂的数学计算 ,函数的返回值不要太大,这样的开销很大。用户自定义函数象光标一样执行的消耗大量的资源,如果返回大的结果采用存储过程

  

  42、不要在一句话里再三的使用相同的函数,浪费资源,将结果放在变量里再调用更快

  

  43、Select COUNT(*)的效率教低,尽量变通他的写法,而EXISTS快.同时请注意区别: select count(Field of null) from Table 和 select  count(Field of NOT null) from Table 的返回值是不同的!!!

  

  44、当服务器的内存够多时,配制线程数量 = 最大连接数+5,这样能发挥最大的效率;否则使用 配制线程数量<最大连接数启用SQL SERVER的线 程池来解决,如果还是数量 = 最大连接数+5,严重的损害服务器的性能。

  

  45、按照一定的次序来访问你的表。如果你先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。如果你(不经意的)某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。如果锁定顺序没有被预先详细的设计好,死锁很难被发现

  

  46、通过SQL Server Performance Monitor监视相应硬件的负载 Memory: Page Faults / sec计数器如果该值偶尔走高,表明当时有线程竞争内 存。如果持续很高,则内存可能是瓶颈。

  Process:

  

  1、% DPC Time 指在范例间隔期间处理器用在缓延程序调用(DPC)接收和提供服务的百分比。(DPC 正在运行的为比标准间隔优先权低的间隔)。  由于 DPC 是以特权模式执行的,DPC 时间的百分比为特权时间百分比的一部分。这些时间单独计算并且不属于间隔计算总数的一部 分。这个总数显 示了作为实例时间百分比的平均忙时。

  

  2、%Processor Time计数器 如果该参数值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。

  

  3、% Privileged Time 指非闲置处理器时间用于特权模式的百分比。(特权模式是为操作系统组件和操纵硬件驱动程序而设计的一种处理模式。它允许直接访问硬件和所有内存。另一种模式为用户模式,它是一种为应用程序、环境分系统和整数分系统设计的一种有限处理模式。操作系统将应 用程序线程转换成特权模式以访问操作系统服务)。特权时间的 % 包括为间断和 DPC 提供服务的时间。特权时间比率高可能是由于失败设备产生的大 数量的间隔而引起的。这个计数器将平均忙时作为样本时间的一部分显示。

  

  4、% User Time表示耗费CPU的数据库操作,如排序,执行aggregate functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接, 水平分割大表格等方法来降低该值。 Physical Disk: Curretn Disk Queue Length计数器该值应不超过磁盘数的1.5~2倍。要提高性能,可增加磁盘 。 SQLServer:Cache Hit Ratio计数器该值越高越好。如果持续低于80%,应考虑增加内存。注意该参数值是从SQL Server启动后,就一直累加记数 ,所以运行经过一段时间后,该值将不能反映系统当前值。

  

  47、分析select emp_name form employee where salary > 3000 在此语句中若salary是Float类型的,则优化器对其进行优化为Convert (float,3000),因为3000是个整数,我们应在编程时使用3000.0而不要等运行时让DBMS进行转化。同样字符和整型数据的转换。

  

  48、查询的关联同写的顺序

  

  select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID =  'JCNPRH39681' (A = B ,B = '号码')

  

  select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID =  'JCNPRH39681' and b.referenceid = 'JCNPRH39681' (A = B ,B = '号码', A = '号码')

  

  select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = 'JCNPRH39681' and a.personMemberID =  'JCNPRH39681' (B = '号码', A = '号码')

  

  49、

  

  (1)IF 没有输入负责人代码 THEN code1=0 code2=9999 ELSE code1=code2=负责人代码 END IF 执行SQL语句为: Select 负责人名 FROM P2000  Where 负责人代码>=:code1 AND负责人代码 <=:code2

  

  (2)IF 没有输入负责人代码 THEN  Select 负责人名 FROM P2000 ELSE code= 负责人代码 Select 负责人代码 FROM P2000 Where 负责人代码 =:code END IF 第一种方法只用了一条SQL语句,第二种方法用了两条SQL语句。在没有输入负责人代码时,第二种方法显然比第一种方法执行效率高,因为它没有限制条件; 在输入了负责人代码时,第二种方法仍然比第一种方法效率高,不仅是少了一个限制条件,还因相等运算是最快的查询运算。我们写 程序不要怕麻烦

  

  50、关于JOBCN现在查询分页的新方法(如下),用性能优化器分析性能的瓶颈,如果在I/O或者网络的速度上,如下的方法优化切实有效,如果在CPU或者内存上,用现在的方法更好。请区分如下的方法,说明索引越小越好。

  

  begin

  

  DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20))

  

  insert into @local_variable (ReferenceID)

  

  select top 100000 ReferenceID from chineseresume order by ReferenceID

  

  select * from @local_variable where Fid > 40 and fid <= 60

  

  end 和

  

  begin

  

  DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20))

  

  insert into @local_variable (ReferenceID)

  

  select top 100000 ReferenceID from chineseresume order by updatedate

  

  select * from @local_variable where Fid > 40 and fid <= 60

  

  end 的不同

  

  begin

  

  create table #temp (FID int identity(1,1),ReferenceID varchar(20))

  

  insert into #temp (ReferenceID)

  

  select top 100000 ReferenceID from chineseresume order by updatedate

  

  select * from #temp where Fid > 40 and fid <= 60 drop table #temp

  

  end

 

另附:存储过程编写经验和优化措施  From:网页教学网

 

  一、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。 

 

  二、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写又没有一定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优 化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。 

 

  三、内容:  

 

  1、开发人员如果用到其他库的Table或View,务必在当前库中建立View来实现跨库操作,最好不要直接使用databse.dbo.table_name,因为 sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。  

 

  2、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,做过自身的查询优化检查。 

 

  3、高程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点:   

 

  a)SQL的使用规范:

 

   i. 尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。

 

   ii. 尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。

 

   iii. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作。

 

   iv. 注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。

 

   v. 不要在where子句中的=左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

 

   vi. 尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。

 

   vii. 尽量使用>=,不要使用>

 

   viii. 注意一些or子句和union子句之间的替换

 

   ix. 注意表之间连接的数据类型,避免不同类型数据之间的连接。

 

   x. 注意存储过程中参数和数据类型的关系。

 

   xi. 注意insert、update操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。   

 

  b)索引的使用规范:

 

   i. 索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。

 

   ii. 尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引

 

   iii. 避免对大表查询时进行table scan,必要时考虑新建索引。

 

   iv. 在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。

 

   v. 要注意索引的维护,周期性重建索引,重新编译存储过程。  

 

  c)tempdb的使用规范:

 

   i. 尽量避免使用distinct、order by、group by、having、join、cumpute,因为这些语句会加重tempdb的负担。

 

   ii. 避免频繁创建和删除临时表,减少系统表资源的消耗。

 

   iii. 在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;如果数据量不大, 为了缓和系统表的资源,建议先create table,然后insert。

 

   iv. 如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用到该临时表的索引。

 

    v. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较 长时间锁定。

 

    vi. 慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用tempdb的系统表。  

 

  d)合理的算法使用:   

 

  根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令:set statistics io on, set statistics time on , set showplan on 等。

 

 

 

 

 

 

 

 

 

 

如何调整Windows参数提高SQL Server性能

 

  SQL Server数据库与Windows操作系统来自同一个家庭,在技术上具有一定的共通性。我们可以调整Windows操作系统的一些参数来提高SQLServer数据库服务器的性能,使之更高效的运行。

 

  一、 提高虚拟内存来提高数据库服务器性能。

 

  虚拟内存简单的来说就是内盘中的一块空间。当物理内存不够时,操作系统会自动把某些驻留在内存中暂时不用的内容移植到这个在硬盘上的虚拟内存中,以释放更多的空间给新的应用程序使用。也就是说,当物理内存使用完时操作系统会拿出一部分硬盘空间来充当内存使用,以缓解内存的压力。为此从某种程度来说,这个虚拟内存的设置也会影响到数据库服务器的性能。那么这个虚拟内存到底该设置多少为好呢?这没有一个固定的标准。这需要数据库管理员根据部署的应用来确定。

 

  如数据库没有一些高级的应用,如数据仓库、全文索引或者不适多个应用服务一身的话,笔者认为只要把虚拟内存设置为物理内存的1.5倍即可。但是,如果在数据库服务器上配置了数据仓库或者全文索引的话,则这个1.5倍的虚拟内存往往是不够的。此时笔者建议需要把虚拟内存配置为物理内存的3倍到四倍。同时,需要调整数据库中的最大服务器内存选项,将其设置为物理内存的1.5倍。也就是说,其在使用内存的时候,可以使用虚拟内存大小的一半。注意这个设置时必须的,否则的话,调整数据库虚拟内存很难起到应有的效果。而且当以后内存升级了,则也需要同时更改这个两个参数。

 

  最后需要说明的一点就是,虚拟内存并不是越大越好。如果设置为10倍、20倍,那么这是浪费。以往内存中没有这么多的内容可以往虚拟内存中存放。所以,针对SQL Server数据库与Windows服务器来说,4倍于物理内存的虚拟内存已经足够了。设置的再大的话,就没有多少的实际意义了。

 

  二、 调整本地客户端的任务优先级。

 

  在数据库初始化的过程中,有大部分的任务需要在本地客户端上完成。即时在后续维护中,出于某种原因仍然要在本地客户端上操作。那么什么是本地客户端呢?其实本地客户端就是跟数据库服务器部署在同一台计算机上的客户端。如我们在导入期初数据的时候,为了方便会在本地客户端上直接进行操作。因为这可以节省数据在网络上传输的时间。

 

  不过在本地客户端上进行操作的时候,往往分为前台运行与后台运行。操作系统这么设计的本意是为了提高远程客户端的执行效率。如在远程客户端生成物料需求计划的时候,由于运算量比较大,其花费的时间可能比较久,如可能需要20分钟。为了提高工作效率,对于类似的作业,应用程序可以把这个运算放置在后台运行。不过需要注意的是,把某个作业放置在后台运行,并不能够节省其运行的时间,而往往由于放置在后台的作业其优先级比较低,往往实际花费的时间还会延长,如会延长到23分钟等等。之所以要把这个长时间运行的作业放置在后台,主要是为了让用户不用干等,可以先作其他事情。等到运行完成后,系统会自动把相关的结果返回给用户。这在感觉上是缩短了运行的时间(往往在等待的过程中时间过得特别慢),而实际上其运行的时间根本没有缩短,甚至会更长。

 

  这个处理策略对于远程客户端来说确实有用,至少可以在感觉上缩短用户的等待时间。而且可以让用户先进行其他的操作。但是如果在本地客户端上,处理某些作业的时候,可能并不希望如此。如在本地客户度进行物料需求计划测试,数据库管理员希望即时把这个计划放置在后台运行,其也能够与前台应用程序具有相同的优先级,以减少这个处理时间。所以,当数据库管理员遇到类似情况时,就需要调整操作系统的相关设置,让作为在后台运行的应用程序,也能够与前台运行的其他应用程序具有相同的优先级。

 

  通常情况下,安装完干净的SQL Server数据库时,服务器任务调度设置为“务”,即前后台应用程序没有优先级的分别。也就是说,此时将为前台应用程序与后台应用程序提供相等的处理时间。但是有时候为了兼顾远程客户端,在部署实例的时候,会改变这设置。如把降低后台应用程序的优先级,让更多的资源能够服务于前台应用程序。在大部分情况下,这个设置是必要的。不过如果出于某些原因需要在本地客户端执行某些操作的话,则数据库管理员需要暂时调整这个配置,以节省某些作业的运行时间。有时候甚至可以将服务器任务调度设置为最大或者应用程序,这就可以为前台应用程序提高最大的处理器时间。

 

  可见,任务调度计划设置也没有一个统一的优劣标准。主要还是需要看数据库服务器到底用来做什么?为此这也对数据库管理员提出了比较高的要求。此时数据库管理员必须要理解各种优先级设置对于数据库服务器性能的影响。然后再根据当时的实际应用来合理的调整任务级别的优先级,以取得本地客户端操作的最大性能。

 

  三、 限制系统内存用户文件缓存的大小。

 

  毋庸置疑,数据库服务器的物理内存对于数据库的性能具有至关重要的影响。但是有时候我们会发现一个奇怪的现象,即即时增加了数据库服务器的物理内存,但是仍然没有发现数据库的性能有很大的改善,或则说比原先的还要差一点。这是什么原因呢?如结合SQLServer数据库来说,这主要是内存的分配不是很合理。如大部分的内存被用来存放文件缓存。此时如果增加的内存都被用来存放文件缓存了,那么光靠简单的增加内存并不能够提高数据库的性能。所以,有时候我们数据库管理员需要优化SQL Server服务器的内存使用情况,如需要限制用户文件缓存的内存量。

 

  那么该如何限制呢?这不是SQLServer数据库服务器来完成的,而是需要通过Windows操作下系统的配置来实现。如要限制文件系统缓存,需要确保没有选择“最大化文件共享数据吞吐量”这个选项(其原来是为文件共享所准备的),然后选择“最小化使用对内存”或者“平衡”选项,来制定最小文件系统缓存。

  具体来说,可以按如下步骤来调整这个选项,以提高服务器的性能。首先,依次打开控制面板、选择网络连接、单击本地连接。然后打开常规选项卡,选择属性。在本地连接属性对话框中选择常规选项卡,选择微软网络的文件和打印机共享,并单击属性。在弹出来的对话框中,去掉“最大化文件共享数据吞吐量”选择,可以选择“最大化网络应用程序的数据吞吐量”。然后按确定即可。如此操作系统就会自动调整内存的分配,不会给文件缓存保留很大的空间,从而可以提高数据库内部处理的性能。往往这对于事务性的应用系统很有作用,能够在很大程度上提高数据库的性能。

 

  不过在调整这个配置后,如果在站台服务器上还部署有文件服务器的话,那么这个文件服务器的性能就会受到比较大的影响。因为对于文件服务器应用来说,需要比较大的文件缓存量。为此在某种程度上来说,数据库服务器与文件服务器在这方面是相互冲突的。数据库管理员就需要相互权衡,然后确定一个最佳的处理方案。不过一般情况下,不建议将数据库服务器与文件服务器、打印服务器等等部署在同一个服务器上。因为这三种不同的应用,彼此之间的资源争用还是很厉害的。为此会给数据库的性能带来比较大的负面影响。

 

  如果光从数据库服务器来说,限制文件缓存的内存使用量,确实可以提高数据库服务器的性能。特别是对于某些特别的应用与计算,由于需要用到比较大的内存,故可以大幅度提高这些作业的运算量。

 

  可见我们在优化数据库性能的时候,有时还不能够光从数据库服务器着手。必要的时候,我们需要换一个角度,从操作系统出发,调整操作系统的相关配置,也能够明显的提高数据库的性能。

 

 

高手详解SQL性能优化十条经验

1.查询的模糊匹配

尽量避免在一个复杂查询里面使用 LIKE '%parm1%'—— 红色标识位置的百分号会导致相关列的索引无法使用,最好不要用.

解决办法:

其实只需要对该脚本略做改进,查询速度便会提高近百倍。改进方法如下:

a、修改前台程序——把查询条件的供应商名称一栏由原来的文本输入改为下拉列表,用户模糊输入供应商名称时,直接在前台就帮忙定位到具体的供应商,这样在调用后台程序时,这列就可以直接用等于来关联了。

b、直接修改后台——根据输入条件,先查出符合条件的供应商,并把相关记录保存在一个临时表里头,然后再用临时表去做复杂关联

2.索引问题

在做性能跟踪分析过程中,经常发现有不少后台程序的性能问题是因为缺少合适索引造成的,有些表甚至一个索引都没有。这种情况往往都是因为在设计表时,没去定义索引,而开发初期,由于表记录很少,索引创建与否,可能对性能没啥影响,开发人员因此也未多加重视。然一旦程序发布到生产环境,随着时间的推移,表记录越来越多

这时缺少索引,对性能的影响便会越来越大了。

这个问题需要数据库设计人员和开发人员共同关注

法则:不要在建立的索引的数据列上进行下列操作:

◆避免对索引字段进行计算操作

◆避免在索引字段上使用not,<>,!=

◆避免在索引列上使用IS NULL和IS NOT NULL

◆避免在索引列上出现数据类型转换

◆避免在索引字段上使用函数

◆避免建立索引的列中使用空值。

3.复杂操作

部分UPDATE、SELECT 语句 写得很复杂(经常嵌套多级子查询)——可以考虑适当拆成几步,先生成一些临时数据表,再进行关联操作

4.update

同一个表的修改在一个过程里出现好几十次,如:

update table1
set col1=...
where col2=...;
update table1
set col1=...
where col2=...
......

象这类脚本其实可以很简单就整合在一个UPDATE语句来完成(前些时候在协助xxx项目做性能问题分析时就发现存在这种情况)

5.在可以使用UNION ALL的语句里,使用了UNION

UNION 因为会将各查询子集的记录做比较,故比起UNION ALL ,通常速度都会慢上许多。一般来说,如果使用UNION ALL能满足要求的话,务必使用UNION ALL。还有一种情况大家可能会忽略掉,就是虽然要求几个子集的并集需要过滤掉重复记录,但由于脚本的特殊性,不可能存在重复记录,这时便应该使用UNION ALL,如xx模块的某个查询程序就曾经存在这种情况,见,由于语句的特殊性,在这个脚本中几个子集的记录绝对不可能重复,故可以改用UNION ALL)

6.WHERE 语句中,尽量避免对索引字段进行计算操作

这个常识相信绝大部分开发人员都应该知道,但仍有不少人这么使用,我想其中一个最主要的原因可能是为了编写写简单而损害了性能,那就不可取了

9月份在对XX系统做性能分析时发现,有大量的后台程序存在类似用法,如:

......
where trunc(create_date)=trunc(:date1)

虽然已对create_date 字段建了索引,但由于加了TRUNC,使得索引无法用上。此处正确的写法应该是

where create_date>=trunc(:date1) and create_date<trunc(:date1)+1< PRE>

或者是

where create_date between trunc(:date1) and trunc(:date1)+1-1/(24*60*60)

注意:因between 的范围是个闭区间(greater than or equal to low value and less than or equal to high value.),

故严格意义上应该再减去一个趋于0的小数,这里暂且设置成减去1秒(1/(24*60*60)),如果不要求这么精确的话,可以略掉这步。

7.Where 语句的法则

7.1 避免在WHERE子句中使用innot  inor 或者having

可以使用 exist 和not exist代替 in和not in。

可以使用表链接代替 exist。Having可以用where代替,如果无法代替可以分两步处理。

例子

SELECT *  FROM ORDERS WHERE CUSTOMER_NAME NOT IN
(SELECT CUSTOMER_NAME FROM CUSTOMER)

优化


SELECT *  FROM ORDERS WHERE CUSTOMER_NAME not exist
(SELECT CUSTOMER_NAME FROM CUSTOMER)

7.2 不要以字符格式声明数字,要以数字格式声明字符值。(日期同样)否则会使索引无效,产生全表扫描。

例子使用:

SELECT emp.ename, emp.job FROM emp WHERE emp.empno = 7369;
不要使用:SELECT emp.ename, emp.job FROM emp WHERE emp.empno = ‘7369’

8.Select语句的法则

在应用程序、包和过程中限制使用select * from table这种方式。看下面例子

使用SELECT empno,ename,category FROM emp WHERE empno = '7369‘
而不要使用SELECT * FROM emp WHERE empno = '7369'

9. 排序

避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序

10.临时表

慎重使用临时表可以极大的提高系统性能

 

 

 

 

 

浅谈如何优化SQL Server服务器

1.数据和日志文件分开存放在不同磁盘上

数据文件和日志文件的操作会产生大量的I/O。在可能的条件下,日志文件应该存放在一个与数据和索引所在的数据文件不同的硬盘上以分散I/O,同时还有利于数据库的灾难恢复。

2.tempdb数据库单独存放在不同磁盘上

tempdb数据库是其他所有数据库都有可能使用的临时数据库。当使用select into、在没建立索引的列上执行Orderby时就会在tempdb数据库中产生临时表来存储中间数据。由于建立和填充临时表会严重降低系统性能,所以在尽可能的情况下应该为要排序的列建立索引。同时,tempdb数据库是为所有的用户和应用程序共享,所以如果一个用户占据了tempdb数据库的所有空间,则其他数据库将不能再使用。在可能的情况下,tempdb数据库应该单独放置在一个速度更快的硬盘或者RAID阵列上。分离tempdb数据库的I/O操作以加快性能。tempdb数据库应该有适当的容量,以满足用户的需要。应该允许tempdb数据库的空间自动增长。如果设置为不允许自动增长,当查询操作建立了超过tempdb数据库容量的临时表时,操作将无法完成。

适当设置tempdb数据库的增长幅度,过小的增长幅度会产生更多的外部碎片,会占用更多的资源。

3.避免热点数据的发生

在SQLServer7.0之前,对于没有聚集索引的表(堆集表),新插入的数据行总是放置在磁盘中表的物理结尾处。如果并发的用户很多,同时在对表执行插入或者更新数据的操作,这将使得十分繁忙的表的末尾有可能产生数据热点。并发的I/O操作集中对少数页面进行操作,将导致数据库性能的下降。

在SQLServer中,新的数据行的物理存储空间的分配是通过PFS页面来进行的。PFS页面的管理算法将插入操作进行分散来尽量避免产生数据热点。

在设计应用系统和数据库时,要避免在自然增长的列上建立主键,这样有可能导致热点数据的发生。

4.数据类型要少

在设计表时,尽可能少用数据类型。这样一个数据页面上可以保存最多的信息。数据页面就少,检索数据页面的I/O操作就少,所以效率会高。

5.监控和整理空间碎片

文件空间的自动增长提高了自动管理性,但可能导致空间碎片。物理空间与数据的逻辑空间不再连续。定期的监控和空间碎片整理有利于提高I/O性能。

6.使用主数据文件和次要数据文件

每个数据库的一个主数据文件属于主文件组。对于1GB左右规模的数据库,一个数据文件就够了,如果有次要数据文件,主数据文件中有管理次要数据文件的指针。

采用多个数据文件时,主数据文件用于存储系统对象和表,次要数据文件用于存储用户数据和索引。在可能的情况下,主数据文件和次要数据文件可以单独存放在不同的磁盘上以分散I/O。

如果采用多个数据文件,推荐主数据文件存储系统数据,次要数据文件存放用户数据和索引,这样会有助于提高I/O性能。

7.利用文件组改善性能

在大型数据库系统中,可以考虑建立文件组来管理数据文件。将表和索引通过存放在不同的物理磁盘上进行性能监控比较,最后得出优化的存储方案。

8.重视自动增长和自动收缩可能导致的性能问题

数据库文件的自动增长和自动收缩功能对于小型数据库的管理十分有用。但可能导致大型数据库的性能问题。因为文件的自然增长的同时会导致存储碎片的发生。当文件空间变大时,新分配的空间不一定和原来的空间连续。当文件空间收缩时,释放了部分空间。然而当文件又需要增长存储空间却不能利用原先释放的空间,也会导致碎片的发生。

9.分离系统数据和用户数据

将系统数据库和用户数据库分开存放在不同的物理磁盘上有助于改善I/O性能,有助于数据库备份和恢复。

10.优化索引设计

索引的设计对数据库的性能十分重要。具体不再阐述,可参见本博相关文章。

11.定期更新统计信息

SQLServer默认使用基于代价的优化,所以统计信息的及时更新对于查询优化十分重要。

12.定期的一致性检查

定期对数据库进行一致性检查,确保数据库的完整性。

 

 

 

 

 

 

 

用并行查询让SQL Server加速运行

 

 

并行查询其优势就是可以通过多个线程来处理查询作业,从而提高查询的效率。SQL Server数据库为具有多个CPU的数据库服务器提供并行查询的功能,以优化查询作业的性能。也就是说,只要数据库服务器有多个CPU,则数据库系统就可以使用多个操作系统进程并行执行查询操作,来加速完成查询作业。

一、并行查询三步走。

并行查询作业在数据库中,主要经过三个步骤。

首先,数据库会判断是否需要进行并行查询。在数据库中有一个查询优化器,会对SQL语句进行优化,然后数据库才会去执行查询语句。而这个查询器在对SQL语句进行查询优化时,其中一个动作就是判断是否需要对SQL语句进行查询优化。也就是说,并不是所有的SQL查询语句都可以从并行查询中获取收益。如果查询优化器认为查询语句可以从并行查询中获取收益的话,则就会将交换运算符插入到查询执行计划中,为并行查询做准备。故哪些语句需要采用并行查询,哪些不需要,这不用数据库管理员关心。数据库查询优化器会帮管理员作出这个决定。数据库管理员需要清楚的是,在哪些情况下,数据库SQL优化器会认为不宜采用并行查询。通常情况下,只要满足以下条件的任何一个,则就不会执行并行查询。一是对于特定的查询,查询优化器认为串行查询执行计划要快于任何可能的并行执行计划;二是查询的串行执行成本并不高,不需要进行并行查询;三是查询中包含无法并行运行的标量运算符或者关系运算符。若从数据库管理员的角度讲,第三个条件对我们具有最大的影响。当数据库预计未来可能利用并行查询来提高数据库性能时,则在数据库设计时,就需要注意避免使用那些无法在并行查询功能中使用的运算符。因为某些关系运算符或者逻辑运算符可能会要求查询计划一定要在串行模式中进行,或者部分需要在串行模式下进行。如此的话,查询优化器就不会利用并行查询功能来提高查询语句的性能。这是数据库管理员在数据库设计时必须要考虑到的一个细节问题。

其次,确定并行的进程数。当查询优化器在查询语句中插入交叉运算符之后,数据库就会执行并行查询。并行查询在执行计划时可以使用多个线程。此时,就又遇到了一个问题,数据库会把这个查询作业分成几个进程操作呢?此时,数据库管理员就需要知道上什么叫做并行度。其实。在处理并行查询的时候,数据需要知道最大可使用的进程与实际使用的进程。而最大可使用的进程就叫做并行度。这个并行度的值是在服务器级别中进行设置,也可以通过系统存储过程来进行修改。但是,最大可使用进程数不一定等于实际是用进程数。实际是用进程数是数据库在查询计划执行时初始化的时候确定的。也就是说,这不用数据库管理员去额外的设定。数据库系统会自动根据计划的复杂程度来确定合理的进程数目。当然其实际采用的进程数不能够超过并行度,即最大可以使用的进程数。

最后执行查询。当以上内容确定好之后,数据库就会执行具体的查询语句。在这一步中,需要注意一个问题。数据库管理员还可以在查询语句中指定MAXDOP查询提示来修改这个进度值。也就是说,如果某个查询作业数据库管理员认为可能会耗时比较久,就可以为这个查询作业设置比较大的进度值。当利用MAXDOP查询提示设置这个并行进度值之后,它会覆盖预先设置的默认值。从而实现针对单个查询语句设置额外的进度值,以提高某些特殊查询作业的性能。

二、并行查询中需要注意的内容。

注意点一:需要注意硬件方面的限制。

并行查询是数据库提高查询性能的一个有力举措。不过其往往受到比较大的约束。如上面提高的一些基于成本考虑之外,还有一些硬性的限制。如通常情况下,只有在数据库服务器有多个微处理器(CPU )的情况下数据库才会考虑执行并行查询。也就是受,只有具有多个CPU的计算机才能够使用并行查询。这是一个硬性的限制条件。另外在查询计划执行过程中,数据库还会判断当时是否有足够多的线程可以使用。每个查询操作都要求一定的线程数才能够执行;而且执行并行计划比执行串行计划需要更多的线程,所需要的线程数也会随着并行度的提高而提高。如果在并行计划执行的时候,当时数据库服务器没有足够的线程让并行计划使用的话,数据库引擎就会自动减少并行度,甚至会放弃并行查询而改为串行计划。所以说,数据库是否能够执行并行查询,要受到其硬件的限制。为此,如果企业真的需要通过并行查询来提高数据库性能的话,则管理员就需要根据情况来调整硬件配置。

  注意点二:不建议对所有查询都使用并行查询。

通常情况下,笔者认为最好只对大型表的连接查询、大量数据的聚合操作、大型结果集的重复排序等等操作才应用并行查询的功能。如果在这些操作上执行并行查询的话,那么其改善数据库性能的效果是非常明显的。相反,如果对于简单查询执行并行查询的话,可能执行并行查询所需要的额外协调工作会大于其潜在的性能提升。所以,数据库管理员在确定是否需要执行并行查询功能的话,需要慎重。笔者的建议是,在数据库服务器级别上,最好不要设置并行查询。即把并行度设置为1或者一个比较小的值。然后对于一些特殊的查询操作,利用MAXDOP查询提示来设置最大的可使用进程数。如此的话,可能会更加的合理。如果有时候数据库管理员不知道是否需要采用并行查询功能的话,则可以通过数据库自带的统计功能进行判断。为了区别并行查询计划到底有没有从并行查询中受益,数据库引擎可以将执行查询的估计开销与并行查询的开销阀值进行比较。并行计划只有对需时较长的查询通常更加有益;因为其性能优势将抵消初始化、同步和终止并行计划所需的额外时间开销。

注意点三:数据库会根据查询所涉及到的行数来判断是否要并行查询。

上面谈到,最好对大型表的连接查询、大量数据的聚合操作、大型结果集的重复排序等等操作才应用并行查询的功能。因为只有如此,并行查询带来的收益才会超过其付出的代价。但是,并不是说连接查询、聚合操作、排序等作业都适合采用并行查询。当数据库在考虑并行查询计划的时候,查询优化器还会去确定所涉及到的行数。如果所涉及到的行数台少,则将不会考虑执行并行查询计划。而会采用串行方式执行查询语句。如此的话,可以避免因为启动、分发、协调的开销大大超过并行执行作业所带来的收益。这本来是一个不错的设计,但是也会给数据库管理员带来一定的麻烦。如现在数据库管理员想要测试并行查询到底可以在多大程度上影响查询操作,就有点麻烦。因为其有数据量的限制。如果数据库管理员需要进行这个测试,还不得不先在数据库系统中导入足够多的数据才行。这就限制了数据库管理员的测试操作。不过话说回来,这个机制仍然是不错的。因为数据库管理员不用去考虑,当数据库规模到多大的时候采用并行查询。

注意点四:同一个操作在不同时候会采用不同的进程数。

上面说到过,并行查询到第采用多少进程数除了跟操作的复杂程度相关外,还直接跟当时的服务器状态相关,如是否有足够的进程数等等。所以,在不同的时间,即使是相同的数据、相同的操作,其并行查询所用的进程数也可能不同。其所需要的时间也就不同了。因为只有在并行查询真正进行的时候,数据库引擎才去收集当前系统的工作负荷,如进程数,和其他对一些配置信息,然后数据库才确定最佳的并行进程数。从查询开始,到这个查询作业结束,将一直采用这个进程数。如果下次要继续查询,则数据库引擎会继续收集这些信息。此时,如果系统工作负荷有所改善,在数据库可能会采用更多的进程数来执行这个查询。从而查询作业的性能会更加的高。相反,如果此时系统的负荷比前一次查询要重了,则数据库就可能会采用比较少的进程来处理这个作业。此时,第二次查询的速度反而更慢了。所以,如果在数据库服务器中同时部署了其他应用,则其他应用所占用系统资源的多少也会对并行执行产生难以估测的影响。

 

 

 

有效使用SQL Server的自动管理功能

如要让数据库进行自动管理,则管理员需要预先定义一些可预测的管理任务以及这些任务发送的条件。当满足这些指定的条件,则数据库会自动运行管理员指定的操作。使用自动管理来处理日常事务,则让管理员可以抽出时间去关注其他的事情,如数据库优化等等更加具有价值的作业。

计划就是自动化管理组件的一个成员。计划指定了作业运行的时间。多个作业可以根据一个计划运行;多个计划也可以应用到一个作业。但是这个时间跟我们普通上的几点几分又有差异。这个时间不仅指特定的日期或者时间,而且还可以表示特定的时间。如当SQL Server代理启动的时候或者服务器的CPU使用率处于定义的空闲状态水平时。也就是说,这里指的时间计划也可以实现一定的条件状态控制。简而言之,计划作业就是定义使得作业在没有哦能够互交互情况下开始运行的条件,包括具体的日期或者特定的在状况。通过为作业创建新计划或者将现有的计划添加到作业可以将作业计划设置为自动运行。不过在设置自动执行计划的时候,需要注意一个问题。即一次只能够运行一个作业实例。如果在作业按计划运行时尝试手工运行该作业,则SQL Server代理将拒绝这个请求。另外,即使计划未启用,作业仍可以为响应警报而运行,或者由用户手动运行。如果作业计划未启用,则任何使用该计划的作业都不会启用该计划。

一、 计划触发的时间与事件。

上面笔者说过,计划可以基于特定的时间与事件而触发。那么这些具体的时间与事件是什么呢?笔者平时用到的最多的就是如下几种情况。

一是特定的日期和时间运行一次。这个计划时间在数据库备份的时候特别有用。大家都知道,数据库备份会占用比较多的系统资源。如果在数据库服务器使用高峰期(如白天上班时间)进行备份的话,那么会对用户的访问造成比较大的影响。为此笔者就把数据库备份的时间放在晚上12点之后。这个时段相对来说,很少有用户会访问数据库。此时管理员就可以利用计划功能,让其在每天的12点之后进行数据库备份。这就是基于特定的日期和时间计划的典型应用。

二是安重复执行的计划运行。这个跟上面讲的特定日期和时间运行一次比较类似。只是上面的情况只运行一次。而这个按重复执行计划运行则是指会重复运行多次。如每天晚上12点都进行数据库备份等等。在实际工作中,特定日期和时间运新一次往往只是针对一些特殊的情况。如今天刚对数据库结构进行了比较大的更改,如添加了几张表或者视图,此时就需要对数据库进行一次完全备份。如故不急于进行备份的话,则就可以建立一个在特定的日期和时间运行的数据库完全备份计划,让其在午后进行数据库备份。但是对于常规的数据库备份,则需要采取这个按重复执行计划运行。

三是当计算机的CPU使用率处于定义的空闲状态水平时。也就是说,数据库服务器当前的CPU使用率比较低,可以执行其他一些比较复杂的管理任务。如有些数据库系统在设计的时候,有一个库存补货点作业。当库存低于安全库存的时候,系统就会自动生成一张物料请购单,来满足安全库存的需要。由于这张表设计到的物料比较多,会占用比较多的系统资源。故可以设置每天运行一次,而运行的时间就定在CPU使用率比较低的时候。如此就可以减少对其他作业造成的负面影响。

二、 CPU空闲计划的典型应用。

其他的几种计划类型,不少数据库管理员已经非常了解。笔者今天想谈的是CPU空闲计划的应用。这个计划如果应用的好的话,可以大大提高数据库的性能。如果要想利用好这个功能,则需要回答如下两个问题。

一是什么作业需要使用CPU空闲计划?这个问题比较难回答。从理论上来说,任何作业都可以采用CPU空闲计划在自动执行。只是他们带来的效果不同。有的作业即使采用了CPU空闲计划,也不能够带来很大的性能改善。简单的来说,一些占用CPU资源比较大的作业,采用CPU空间计划规则来自动执行,可以取得比较好的效果。如数据库有时候需要重新生成索引,这项工作会占用比较多的CPU资源。而且随着数据量的增多,这个CPU使用率也会越来越高。为此,如果可以把重新生成索引的作业,放在CPU空闲时间来进行的话,那么对于提高数据库的性能效果是比较明显的。总之当某个作业比较复杂,可能需要占用到比较多的CPU或者内存资源的话,则可以采用这个CPU空闲计划。

二是什么时候CPU是空闲的?空闲是一个相对的标准。有时会CPU使用率30%以下可以定义为空闲;而有时候CPU使用率只有不到60%,就是空闲。这要根据服务器的配置已经所部属的应用来考虑。所以管理员在采用CPU空闲计划之前,先要对服务器进行观测一定时间,采用性能监视器等工具来监视服务器流量并收集相关的统计信息。然后利用收集到的信息来分析CPU空闲的标准,并在数据库中进行相关的设置。将 CPU 空闲条件定义为一个百分比,在该百分比以下,CPU 使用率必须持续指定的时间。然后,设置持续时间长度。如果 CPU 使用率在指定时间内低于指定的百分比,则 SQL Server 代理将启动具有 CPU 空闲时间计划的所有作业。如管理员认为CPU使用率在35%以下可以运行重建索引的作业,即当这个重建索引作业运行时CPU使用率在可以忍受的范围之内,此时就可以把CPU的空闲率标准设置为35%。而且这个低于35%的CPU使用率必须要持续一段时间。如这个低于35%的CPU持续时间很短,那么系统仍然不会认为这个CPU是出于空闲状态。这个持续时间最好能够参考具体作业的执行时间。若重建索引作业所需要的时间等等。

三、 如何停止计划的自动执行?

有些时间我们可能并不需要自动执行计划。如在数据库设计的时候,管理员并不需要这些自动执行的计划。为此需要把他们暂时停止。此时有哪些方法可以做到这一点呢?

一是可以把计划与作业剥离。计划与作业是两个独立的内容。如数据库完全备份与计划时间就是相互独立的。如果设置好了数据库完全备份的策略,但是没有把计划时间与这个作业进行关联的话,则数据库完全备份不会自动执行。此时如果需要执行这个作业的话,则就要进行手工启动。故当管理员暂时不想要某个计划的时候,可以把计划作业剥离,即在作业中去掉这个时间计划即可。

二是禁用作业或者计划。当管理员不需要某个作业自动运行的时候,可以把这个计划或者作业进用掉。禁用计划或者禁用作业都会让某个作业停止自动运行,但是他们仍然有微小的差异。如禁止计划的话,只是这个这个作业停止自动运行,但是管理员仍然可以手工执行它。可是禁用作业的话,则系统不仅不会自动运行,而且管理员还不能够手工执行它。这就好像给这个作业设置了终身监禁。为此,为了避免这种情况的发生,笔者是建议最好采用禁用计划而不是禁用作业。如此的话,在必要的时候管理员还可以手工启动该作业来应急。另外,如果这个计划将来仍然需要采用的话,笔者不建议把计划与作业剥离的方式来停止计划的自动执行;而是建议这种禁用计划的方式来完成。不然的话,下次需要的时候仍然需要把计划与作业关联,反而会增加工作量。

另外,如果这个测试计划以后再也不用时,有两种处理方法。一是把计划直接删除。这个是最彻底的方法,但是不会留下任何历史纪录。二是先把计划跟作业玻璃,然后再禁用这个计划。这虽然比较麻烦一点,而且会在数据库中留下垃圾数据。但是却可以保留历史纪录。这可能会对数据库的后续维护带来一定的帮助。到底不用的计划是删除还是禁用,没有一个统一的标准。还是需要根据数据库管理员的操作习惯来判断。

无论采取哪种方式,管理员都需要注意两点内容。一是必须显示的重新启动已禁用的计划。如果管理员只是更改了已禁用的计划策略,并不会重新启动这个计划,而需要管理员手工的启动。二是即使计划未启用,作业仍可以为响应警报而运行,或者由用户手动运行。如果作业计划未启用,则任何使用该计划的作业都不会启用该计划。

 

 

SQL Server数据库优化经验总结(1)

优化数据库的注意事项:

1、关键字段建立索引。

2、使用存储过程,它使SQL变得更加灵活和高效。

3、备份数据库和清除垃圾数据。

4、SQL语句语法的优化。(可以用Sybase的SQL Expert,可惜我没找到unexpired的序列号)

5、清理删除日志。

SQL语句优化的基本原则:

1、使用索引来更快地遍历表。

缺省情况下建立的索引是非群集索引,但有时它并不是最佳的。在非群集索引下,数据在物理上随机存放在数据页上。合理的索引设计要建立在对各种查询的分析和预测上。一般来说:①.有大量重复值、且经常有范围查询(between, >,< ,>=,< =)和order by、group by发生的列,可考虑建立群集索引;②.经常同时存取多列,且每列都含有重复值可考虑建立组合索引;③.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。

2、IS NULL 与 IS NOT NULL

不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。

3、IN和EXISTS

EXISTS要远比IN的效率高。里面关系到full table scan和range scan。几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。

4、在海量查询时尽量少用格式转换。

SQL Server数据库优化经验总结(2)

5、当在SQL SERVER 2000中,如果存储过程只有一个参数,并且是OUTPUT类型的,必须在调用这个存储过程的时候给这个参数一个初始的值,否则会出现调用错误。

6、ORDER BY和GROPU BY

使用ORDER BY和GROUP BY短语,任何一种索引都有助于SELECT的性能提高。注意如果索引列里面有NULL值,Optimizer将无法优化。

7、任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。

8、IN、OR子句常会使用工作表,使索引失效。如果不产生大量重复值,可以考虑把子句拆开。拆开的子句中应该包含索引。

9、SET SHOWPLAN_ALL ON 查看执行方案。DBCC检查数据库数据完整性。DBCC(DataBase Consistency Checker)是一组用于验证SQL Server数据库完整性的程序。

10、谨慎使用游标

在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行操作,这样可使性能得到明显提高。

注释:所谓的优化就是WHERE子句利用了索引,不可优化即发生了表扫描或额外开销。经验显示,SQL Server性能的最大改进得益于逻辑的数据库设计、索引设计和查询设计方面。反过来说,最大的性能问题常常是由其中这些相同方面中的不足引起的。其实SQL优化的实质就是在结果正确的前提下,用优化器可以识别的语句,充份利用索引,减少表扫描的I/O次数,尽量避免表搜索的发生。

其实SQL的性能优化是一个复杂的过程,上述这些只是在应用层次的一种体现,深入研究还会涉及数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计。

 

 

 

 

 

 

 

 

 

 

 

 

 

帮助首页»建站技术»其他

Windows2003优化集合

2007-08-29 11:19

 刚装完2003后我们应该按照如下的方法设置一下:

   1、启用声卡: 系统安装后,声卡是禁止状态,所以要在控制面板 →声音→ 启用,重启之后再设置 它在任务栏显示(如果你使用的是Windows server 2003标准版已允许声音服务,可省略此步)。打开“开始”→ “运

行”→键入“Services.msc ”,在出现的窗口中找到“Windows Audio”并双击它,然后在启动模式的下拉菜单选择“

自动”,并点击“应用”→“开始”→ “确定”

    2、把更多资源分配给程序:右键点击“我的电脑”→属性→高级 →性能→设置→高级,把“处理器计划”和内存

使用分配给“程序”使用,然后点击“确定”。

    3、禁用配置服务器向导:禁止“配置你的服务器”向导的出现:在控制面板→ 管理员工具→管理你的服务器,然

后在窗口的左下角复选“登录时不要显示该页。

    4、禁用Internet Explorer Enhanced Security 和禁止安全询问框的出现:在IE工具选项中自定义设置IE的安全级

别。在”安全“选项卡上拉动滚动条把Internet区域安全设置为”中“或“中低”。自定义设置中将有关的选择“提示

”修改为选择“禁止”或“启用”。

    5、禁用关机事件跟踪:开始→运行→gpedit.msc →计算机配置→管理模板→系统 →显示关机事件跟踪→禁用。

    6、禁用开机 CTRL+ALT+DEL和实现自动登陆:管理工具→ 本地安全策略 →本地策略→ 安全选项 →interactive

logon: Do not require CTRL+ALT+DEL,启用之。

    7、硬件和DirectX加速:

     硬件加速:桌面点击右键→属性→设置→高级→疑难解答。把该页面的硬件加速滚动条拉到“完全”,点击“确定

”保存退出。这期间可能出现一瞬的黑屏是完全正常。

     DirectX加速:“开始”→ “运行”,键入“dxdiag”,打开“DirectX 诊断工具”,在“显示”页面,点击

DirectDraw, Direct3D and AGP Texture 加速三个按钮启用加速。把“声音的硬件加速级别”滚动条拉到“完全加速”



     8、启用桌面主题和文件:“开始”→ “运行”,键入“Services.msc ”,选themes“主题”(默认是禁止的)

,然后改为“自动”,按“应用”,选“开启”。接着点“桌面”的属性,在“主题”里选“windows xp” Windows

Server 2003默认显示所有的文件夹。

     9、允许内置的IMAPI CD-Burning服务和支持Windows影像设备服务:启用Windows内置的IMAPI CD-Burning服务:

“开始”→ “运行”,键入“Services.msc ”,在出现的窗口中找到“IMAPI CD-Burning COM Service ”并双击它,

然后在启动模式的下拉菜单选择“自动”,并点击“应用”→“开始”→ “确定”。

    10、 假如你有如数码相机和扫描仪之类的影像设备,应该打开Windows Image Acquisition 服务:

“开始”→ “运行”,键入“Services.msc ”,在出现的窗口中找到“Windows Image Acquisition (WIA) ”并双击

它,然后在启动模式(startup type )的下拉菜单选择“自动”,并点击“应用”→“开始”→ “确定”

    11、禁用错误报告:右键点击“我的电脑”→属性→高级→点击“错误报告”按钮,在出现的窗口中把“禁用错误

报告”选上并复选“但在发生严重错误时通知我”。

    12、调整虚拟内存:一些朋友经常会对关机和注销缓慢感到束手无策,解决办法就是禁用虚拟内存,这样你的注销

和关机时间可能会加快很多。右键点击“我的电脑”→属性→高级→性能→设置→高级,点击“虚拟内存”部分的“更

改”,然后在出现的窗口选择“无分页文件”。重启系统即可。

2003中文版全面优化

1、 缩短等待时间
打开注册表编辑器,找到 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control,将WaitToK illServiceTimeout 设为:4000(原设定值:20000)。
找到 HKEY_CURRENT_USER\Control Panel\Desktop 键,将右边窗口的 WaitToKillAppTimeout 改为 4000(原设定值:20000),即关闭程序时仅等待1秒。将 HungAppTimeout 值改为:2000(原设定值:5000),表示程序出错时等待0.5秒。
2、 让系统自动关闭停止响应的程序
打开注册表 HKEY_CURRENT_USER\Control Panel\Desktop 键,将 AutoEndTasks 值设为 1(原设定值:0)。

3、 加速共享查看
打开注册表编辑器,把HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Curr entVersion\Explorer\RemoteComputer\NameSpace下的 {D6277990-4C6A-11CF-87-00AA0060F5BF} 删掉

4、 加快Windows 2003的启动:

(1)HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Sessi onManager\MemoryManagement\PrefetchParameters,其中有一个键值名为Enabl ePrefetcher,多数情况下它的值是3,推荐设置值是1.

(2)"我的电脑"->"属性"->"高级"->"启动和故障修复"中,点"错误报告",选择"禁用错误汇报 "、"但在发生严重错误时通知我"。

(3)点击"编辑",在弹出记事本文件中:
  [Operating Systems>
  timeout=30 //把缺省时间 30 秒改为 0 秒

5、优化“启动和故障恢复”设置:
右键单击“我的电脑”,点击属性,点击“高级”,在“启动和故障恢复”一栏中,点击“设置”,其中的“系统失败”一栏中,只选择 “自动重新启动”,写入调试信息选择“无”。

6、关闭“Internet时间同步”功能:
请依次单击“开始”→“控制面板”→“日期、时间、语言和区域选项”,然后单击“日期和时间”→“Internet时间”。

7、关闭华医生Dr.Watson:
在"开始"->"运行"中输入"drwtsn32"命令,或者"开始"->"程序"->"附件"->" 系统工具"->"系统信息"->"工具"->"Dr Watson",调出系统里的华医生Dr.Watson ,只保留"转储全部线程上下文"选项,否则一旦程序出错,硬盘会读很久,并占用大量空间。如以前有此情况,请查找user.dm p文件,删除后可节省几十MB空间。

8、取消对zip文件的支持:
运行,敲入:regsvr32 /u zipfldr.dll 然后回车即可。 (注:最好不要使用,否则不能打开有些压缩文件,即使你装了WinRAR!)

9.windows2003的内存优化!!!!!!!!!!!!(警告!!!!!以下设置需要有256M以上的内存才能有好的效 果!!!)
注册表:
HKEK_LOCAL_MACHINESYSTEMCurrentControlSetControlSessionM anagerMemory Management
中的:禁用内存页面调度: DisablePagingExecutive 值改为“1”
提升系统缓存: LargeSystemCache 值改为“1”

10.修改cpu的二级缓存
在正常情况下,2003会自动识别cpu的二级缓存。但有时2003不会这样做,这样就需要手动优化以改善cpu的性能。
a.)运行"regedit";
b.)去"[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSe ssion Manager
Memory ManagementSecondLevelDataCache>";
c.)修改他的十进制:
   AMD Duron: 64(kb);
  CeleronA/celeron2/3:128;
  PII mobile/PIII E(E/P4A/AMD K6-3/AMD THUNDERBird/Cyrix III:256;
  AMD K6-2/PII/PIII katmai/P4B/AMD Athlon:512;
  PII Xeon/PIII Xeon:1024;
e.)重启。

11.修改磁盘缓存以加速xp
a.)运行 "regedit";
b.)去[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSes sion Manager
Memory ManagementIoPageLockLimit>;
c.)根据你的内存修改其十六进制值:
64M: 1000;
128M: 4000;
256M: 10000;
512M或更大: 40000.
d.)重启

12.减少磁盘扫描等待时间
在dos下,键入“chkntfs/t:0”

13.解除带宽限制
运行----gpedit.msc-----管理模版-----网络----QoS数据包调度程序---限制可保留带宽---启

动-----下面输入 0 ----确定---------在你的拨号图标右健属性找到网络-----看看有没有QoS

数据包调度程序-------如果没有点安装-----服务------添加----选QoS数据包调度程序----看

看有没有打勾----有就代表成功了--------重启---ok!

14使用xp主题
打开控制面板->管理工具->服务,在里面把theme这个服务启动,重启
然后进桌面属性,在桌面主题里面选xp样式,就可以换回熟悉的XP主题!

15.禁用配置服务器向导
由于不需要服务器设置功能,首先我们先禁止“配置你的服务器”向导的出现,你可以在控制面板
-> 管理员工具-> 管理你的服务器 运行它,然后在窗口的左下角复选“登录时不要显示该页”

16.建立一个新的用户账号
打开“开始” -> “运行” -> 键入“lusrmgr.msc ”,你将看到本地用户和组,右键点击左边窗口的“用户”,选择“新用户”.在弹出的对话框中输入账号信息,然后点击“建立”这样 你的账号就可用了,当然,你可以选择把你的账号添加到管理员组,右键点击你新建的用户。然后选择“属性” ->
点击“隶属于” -> “添加” -> “高级” -> “现在查找”在查找结果对话框中双击“管理员”,再点击两次“确定”后关闭“本地用户和组”,现在你将可以注销Administ rator用户用你自己的账号登录系统。
17.禁用Internet Explorer Enhanced Security
作为新windows组件出现的IE安全插件--Internet Explorer Enhanced Security默认把你IE安全设置为最高。这样你将在访问站点弹出询问框并对你浏览网页及文件下载做出阻止的行为。我们其实 不一定需要这个组件。我们首先禁止询问框的出现,在弹出的对话框中复选”以后不要显示这个信息
然后,我们可以在IE工具选项中自定义设置IE的安全级别。在安全选项卡上拉动滚动条把Internet区域安全设置为中,这个 级别将适合大多数人,要是你有特别要求,这个步骤将不适合你。通过对IE安全的设置,你现在安装可以上Sun''s Java VM!
当然,你也可以在控制面板--添加程序--添加或删除Windows组件中卸载Internet Explorer Enhanced Security 。

18.安装Java VM
Windows server 2003没有集成MS Java VM或Sun Java VM,你可以自行下载并安装它。

19.禁止关机事件跟踪
关机事件跟踪也是Windows server 2003区别于其他工作站系统的一个设置,对于服务器来说这是一个必要的选择,但是对个人用户却没什么用,我们同样可以禁止它。 打开开始->“运行” ->输入“gpedit.msc ”,在出现的窗口的左边部分,选择 “计算机配置”-> “管理模板”-> “系统”在右边窗口双击“显示关闭事件跟踪程序”在出现的对话框中选择“禁止”,点击然后“确定”保存后退出。这样,你将看到类 似于windows 2000的关机窗口

20.启用硬件和DirectX加速
★硬件加速:桌面点击右键--属性 -> 设置--高级--疑难解答。把该页面的硬件加速滚动条拉到“完全”,点击“确定”保存退出。这期间可能出现一瞬的黑屏是完全正常 。

★DirectX加速:打开“开始” -> “运行”,键入“dxdiag”并回车打开“DirectX 诊断工具”,在
“显示”页面,点击DirectDraw, Direct3D and AGP Texture 加速三个按钮启用加速。

21.允许声音加速
如果你使用的是Windows server 2003标准版请从第二步操作,因为标准版已允许声音服务。
★打开“开始” -> “运行”,键入“Services.msc ”,在出现的窗口中找到“Windows Audio”并双击它,然后在启动模式的下拉菜单选择“自动”,并点击“应用” ->“开始” -> “确定”
★打开“开始” -> “运行”,键入“dxdiag”并回车打开“DirectX 诊断工具”,在“Sound”页面,把“声音的硬件加速级别”滚动条拉到“完全加速”。

23.允许内置的IMAPI CD-Burning服务和支持Windows影像设备服务
★假如你希望启用Windows内置的IMAPI CD-Burning服务。做如下操作:
打开“开始” -> “运行”,键入“Services.msc ”,在出现的窗口中找到“IMAPI CD-Burning COM Service ”并双击它,然后在启动模式的下拉菜单选择“自动”,并点击“应用” ->“开始” -“确定”
★假如你有如数码相机和扫描仪之类的影像设备,你应该打开Windows Image Acquisition 服务。
打开“开始”-> “运行”,键入“Services.msc ”,在出现的窗口中找到“Windows Image Acquisition (WIA) ”并双击它,然后在启动模式的下拉菜单选择“自动”,并点击“应用” ->“开始”-> “确定”

24.高级设置
★右键点击“我的电脑”--属性--高级--性能--设置--高级,把“处理器计划”和内存使用分配给“程序”使用,然后点击“ 确定”。

25.自动登陆
Windows Server 2003默认是使用"CTRL-ATL-DEL to login" 对话框来登陆Windows的,不过我们我们可以使用Windows XP的Tweak UI来使Server 2003自动登陆。
下载:Tweak UI http://www.ssite.org/uppic/sun_p ... ver2003/tweakui.exe
下载后直接执行tweakui.exe
在左边的面板中选择Logon -> Autologon -> 在右边勾选Log on automatically at system startup输入你的用户名和域名(如果没有就不写)
点击下面的Set Password,输入用户名的密码,然后点击OK。
虽然同样的功能通过修改注册表也能完成,但是修改注册表的方法密码在注册表中表现的是明文,而Tweak UI在注册表中不会留下明文的密码,所以推荐使用Tweak UI来完成这项工作。

26.安装DirectX 9a
在Windows Server 2003上安装DirectX 9a和在其他版本的Windows上安装DirectX 9a的方法是一样的。安装之前先启用DirectX and Graphics Acceleration。 安装完成后重启。

27.设置虚拟内存
我的电脑---高级----设置----性能选项-----高级-----虚拟内存-----更改-----选择驱动器(最好选 在不怎么使用的分区)-------自定义大小(物理内存不大于256M时,设为物理内存的2倍,最大和最小都一样;物理内存不 小于512M时,设为物理内存的1.5倍,最大和最小都一样)确定,重启。

28.把Internet Explorer的临时文件设到不常使用的分区-----工具---Internet选项----Internet临时文件-- ---设置------移动文件夹----选择路径----确定

29.装2003的分区最好别再装其他应用软件,这样系统盘不易产生碎片;每周整理一次文件碎片(注:整理碎片对硬盘损伤较大! 不建议经常使用!)
30.对windows优化大师有信心的,可以使用最新版5.4进行一些优化;最好每隔几天就用优化大师清理一下注册表(注:反 正我用大师从来没有出过事情!)

31.杀毒软件可用诺顿8.0或8.1企业版;KV2003,我已测试均能正常运行
  **设置个性的启动信息或警告信息:
个性化的Windows XP启动:打开注册表编辑器,找到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Window s NT\CurrentVersion\Winlogon子键分支,双击LegalNoticeCaption健值,打开“编辑字 符串”对话框,在“数值数据”下的文本框中输入自己想要的信息标题,如“哥们儿,你好!”,然后点击“确定”,重新启动。
如果想要改变警告信息的话可以双击LegalNoticeText健值名称,在出现的“编辑字符串”窗口中输入想要显示的警告信 息,单击“确定”,重新启动。

Windows XP优化指南

动手前的准备

  动手之前,首先要确保以管理员的身份登录操作系统,因为普通用户身份下好些选项是无权使用的。接下来请激活清晰字体(ClearType),ClearType能使桌面的文字看起来更加清晰易读——这对于手提电脑或液晶显示器用户尤其重要,关闭清晰字体ClearType打开清晰字体Cleartype.
     要激活ClearType,请打开控制面板的显示属性,点击“Appearances(外观)”选项卡,然后点击“Effects...(...效果)”按钮,就会弹出如下对话框:勾上“Use the following method to smooth edges of screen fonts...(用下列方法圆滑屏幕字体边缘)”并在下拉菜单中选择“ClearType(清晰字体)”,然后点击OK(确定),Apply(应用)按钮。效果好多了吧?下面我们看看其它的优化!
     优化一——MsConfig
     大多数朋友都应该熟识MsConfig了,这是一个系统内置的Windows设置工具。点击开始菜单,选择“运行”,然后在录入框中敲入“msconfig”回车。我们要动手脚的是“Startup(启动)”选项卡,这个选项卡中显示了Windows启动时运行的所有程序。这里没有一个程序对Windows来说是生死悠关的,所以放心大胆地把不要的去掉。图中可以看到,笔者把NDetect(ICQ的启动程序)和WinAmpa(就是MP3播放器Winamp了)。把部分勾勾去掉之后,Windows启动会快些,同时空闲的系统资源也会多出一些。
    优化二——其它启动优化
    这是Windows启动过程的更详细列表,凡是在名字右边标着“Automatic(自动)”的项目都是Windows启动时运行的软件。鼠标单击选中其中一条,就会显示出一些文字,说明它有什么作用。中果决定不需要某种服务,只要右键点击它,把属性中的“Automatic(自动)”改为“Manual(手动)”就得了。
    优化三——IE网络浏览器加速技巧
    Windows XP自带Internet Explorer 6,有个小技巧,修改之后启动得飞快(在我的机子上,简直是瞬间启动)。有些朋友试过为“半条命”游戏建个快捷方式,用一定方法修改之后启动加快,这里也是同样原理。右键点击Internet Explorer快捷图标(如任务栏上的快捷启动栏中那个IE图标),打开图标属性之后在“Target(目标)”后面加上“-nohome”参数.
    优化四——菜单延迟
    另一个简单的优化小把戏,就是把滑出菜单时的延迟去掉。修改这个,要用到注册表编辑器(点击开始——>运行,然后敲入“regedit”回车)。要修改的键值在 HKEY_CURRENT_USERControl PanelDesktop。具体要修改的键名是MenuShowDelay——只需把值改为0就得了。记住,要重新启动计算机后更改才生效。
    优化五——GPEDIT和Autoplay
    Windows XP自带了一个非常好用的优化文件,它就是gpedit.msc。开始——>运行,敲入“gpedit.msc”并回车。这是一个非常有效的编辑工具,可以非常方便地修改一些常见的设置。譬如,你不喜欢CD自动播放的话,用这个工具修改再简便不过了,运行gpedit.msc之后,依次点击Computer Configuration(计算机设置)——>Administrative Templates (管理模板)——>System(系统),这里可以看到一个“Turn off Autoplay(关闭自动运行)”值,右键点击它选择“属性”.
    优化六——寻找“添加/删除”菜单中隐藏了的选项
    不喜欢MSN Messenger吗,或是想把Windows Media Player媒体播放器给删掉?可惜打开控制面板中的“添加/删除程序”,Windows XP自带的程序都不在里面。其实很容易找到,只需用记事本打开Windowsinfsysoc.inf文件,找到类似下面这一段:
[Components]
NtComponents=ntoc.dll,NtOcSetupProc,,4
WBEM=ocgen.dll,OcEntry,wbemoc.inf,hide,7
Display=desk.cpl,DisplayOcSetupProc,,7
Fax=fxsocm.dll,FaxOcmSetupProc,fxsocm.inf,,7
NetOC=netoc.dll,NetOcSetupProc,netoc.inf,,7
iis=iis.dll,OcEntry,iis.inf,,7
com=comsetup.dll,OcEntry,comnt5.inf,hide,7
dtc=msdtcstp.dll,OcEntry,dtcnt5.inf,hide,7
IndexSrv_System = setupqry.dll,IndexSrv,setupqry.inf,,7
TerminalServer=TsOc.dll, HydraOc, TsOc.inf,hide,2
msmq=msmqocm.dll,MsmqOcm,msmqocm.inf,,6
ims=imsinsnt.dll,OcEntry,ims.inf,,7
fp_extensions=fp40ext.dll,FrontPage4Extensions,fp40ext.inf,,7
AutoUpdate=ocgen.dll,OcEntry,au.inf,hide,7
msmsgs=msgrocm.dll,OcEntry,msmsgs.inf,hide,7
RootAutoUpdate=ocgen.dll,OcEntry,rootau.inf,,7
IEAccess=ocgen.dll,OcEntry,ieaccess.inf,,7

这是当前所有已安装部件列表,继续前面MSN Messenger的例子,这个程序条目名是“msmsgs”,在倒数第三行。可以看到被我标为红色的“hide”字样,就是这个参数在控制Windows“添加/删除程序”中不显示这一项。只需把“hide”删掉就得了,如下:
msmsgs=msgrocm.dll,OcEntry,msmsgs.inf,hide,7

改为:

msmsgs=msgrocm.dll,OcEntry,msmsgs.inf,,7
现在重新启动计算机,就可以在“添加/删除程序”列表里看到MSN Messenger了。如果想要在添加/删除程序里看到所有的已安装组件,只需用记事本打开sysoc.inf文件,用记事本的查找/替换功能把所有“,hide”替换为“,”就行了。
      
     优化七——关闭Windows的文件保护

警告:这样修改之后可以直接删除Windows的关键文件。
默认状态下系统禁止用户删除系统和程序文件,经过修改注册表可以彻底解除这个限制。打开注册表找到HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows
NTCurrentVersionWinlogon 中的SFCDisable,把它的值改为0xFFFFFF9D.如果要用文件保护,重新把它值改为0就行了。
                                                                                                                优化八——关闭计算机时自动结束任务
                                                                                                                在关机的时候,有时会弹出讨厌的对话框,提醒某个程序仍在运行,是否结束任务。其实完全可以通过一点点修改让Windows自动结束这些仍在运行的程序。在注册表中打开HKEY_CURRENT_USERControl PanelDesktop 目录,把里面的AutoEndTasks键值改为1:注:可能会找不到AutoEndTasks键值,如果是这样的话,自己建一个串值并把它改为这个名字,值设为1就可以了。

      优化九——内存性能优化
      Windows XP中有几个选项可以优化内存性能,它们全都在注册表下面位置:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControl
Session ManagerMemory Management
禁用内存页面调度(Paging Executive)
在正常情况下,XP会把内存中的片断写入硬盘,我们可以阻止它这样做,让数据保留在内存中,从而提升系统性能。要注意的是,拥有很多内存的用户(256M以上)才好使用这个设置。这个设置的名字正如它的功能一样,叫“DisablePagingExecutive”。把它的值从0改为1就可以禁止内存页面调度了。
提升系统缓存
把LargeSystemCache键值从0改为1,Windows XP就会把除了4M之外的系统内存全部分配到文件系统缓存中,这意味着XP的内核能够在内存中运行,大大提高系统速度。剩下的4M内存是用来做磁盘缓存的,在一定条件下需要的时候,XP还会分配更多一些。一般来说,这项优化会使系统性能得到相当的提升,但也有可能会使某些应用程序性能降低。正如前面所说的,必须有256M以上的内存,才好激活LargeSystemCache,否则不要动它。
输入/输出性能
这个优化只对server用户才有实在意义——它能够提升系统进行大容量文件传输时的性能。在默认情况下,这个键值在注册表中是不存在的,必须自己建一个DWORD(双字节值)键值,命名为IOPageLockLimit。多数人在使用这项优化时都发现8到16M字节之间性能最好,具体设什么值,可以设进去试试看哪个值可以获得最佳性能。记住这个值是用字节来计算的,因此,譬如你要分配12M的话,就是12 * 1024 * 1024,也就是12582912。跟前面的内存优化一样,只有当你的内存大于256M的时候才好更改这里的值。
                                                                                                                优化十——加速共享查看
                                                                                                                这是一项很棒的优化,在找到这项优化之前,我经常在漫长地等待窗口显示其它机子上的共享目录中敲破头皮。通常情况下,当Windows XP连接到其它计算机时,会检查对方机子上所有预定的任务——这真是多余,而且还会让你等上30秒钟,实在太糟糕了。所幸的是,很容易就可以把这个过程给禁掉。首先,在注册表中找到HKEY_LOCAL_MACHINESoftwareMicrosoftWindows/Current
VersionExplorerRemoteComputerNameSpace。在这里面,应该有个
{D6277990-4C6A-11CF-8D87-00AA0060F5BF}键。只需把它删掉,重新启动计算机后,Windows就不再检查预定任务了,速度明显提高!

     优化十一——手动指定进程次序
                                                                                                               同时按下Control+Alt+Delete三个键,然后点击“Processes(进程)”选项卡,可以看到一个如上图所示的对话框,在这里可以看到目前正在运行的所有进程。如果要为一个程序分配更多的进程时间,如3D Studio Max,只需右键点击这个进程,再把鼠标指针向下移动到“Set Priority>(设置优先级)”,然后选择你想要这个程序处在哪个优先级。当我接收email时,我会把3DMAX设为“标准”,但当我离开计算机的时候,我会把它的优先急提升为最高的“实时”,这样可以计算机更专注更快速地处理3D动作。

     优化十二——为IRQ中断请求排优先次序
                                                                                                               这是本优化指南的最后一项优化,也是一项非常有效的优化。计算机的每一个主要部件都设了个IRQ中断号。这里就是要通过修改每个IRQ请求的优先次序达到优化目的。这里主要的优化对象是系统/CMOS实时钟,它通过主板来提升性能。首先,要确定你想要哪个组件获得更高的性能,然后找到这个硬件正在使用的IRQ中断号。怎么找呢?打开控制面板里的系统属性(也可以按键盘上的Windows+Break热键组合打开它)。选中“硬件”选项卡,然后点击“设备管理器”按钮。
右键点击要查IRQ号的组件,选择“属性”,然后点击“资源”选项卡。
这里可以看到设备正在使用的IRQ中断号(如果没有IRQ中断号,选择另一个设备)。把中断号记下来,然后运行注册表编辑器regedit,找到注册表中的HKEY_LOCAL_MACHINESystemCurrentControlSetControl
PriorityControl 位置。我们要在这里建立一个名为IRQ#Priority(其中“#”是具体的IRQ中断号)的DWORD双字节值,然后把它的值设为1。譬如说,我的系统CMOS实时钟的IRQ中断号是8,我要建立的键名就是IRQ8Priority。

重新启动计算机之后,就会发现刚优化过的组件性能有所提高。笔者强烈建议用这个方法优化系统CMOS实时钟,因为它能改善整块主板的性能。当然也可以把多个IRQ中断号优先级提高,但这样做的效果没那么好,而且有可能造成系统不稳定。要把这个优化设置撤消的话,只要把刚才建立的注册表键值删掉就OK了。

WINDOWS XP终极減肥大法

WINDOWS XP终极減肥大法

   xp用起来确实不错,但是体积有点太大了,最初的安装就有1.3g,如果是使用 免激活的英文2600+中文汉化包体积会更大。我在网上收集众多高人的经验和 我的本人的意见作出xp终极瘦身大法,在这里跟大家分享。
1. 删除系统文件备份 sfc.exe /purgecache (一般用户是不怎么用的)

2 删除驱动备份 windowsdriver cachei386目录下的Driver.cab文件 (73mb)

3. 取消系统还原 (总体来说系统还原功能还是不错的,建议除了xp安装的那个 盘使用,其它盘都别用,如果哪一天硬盘的空间不够了,可以通过系统清理程 序删除一些比较早的还原点)

4、删除帮助文件(减掉40多mb) (使用中文汉化包的文件大小为92兆,刚开始 使用xp的同志最好别删)

5、删掉WINDOWSsystem32dllcache下文件(减去200——300mb)。

(这是备用的dll文件,只要你拷贝了安装文件,完全可以这样做。既然这样删你 没话说)

6、把我的文档、IE的临时文件夹都转到其他盘(分区)。 (同时对系统的速 度,和硬盘都有好处,如果使用的是双系统,最好把两个系统的IE临时文件都 放在同一个文件夹,这样既加快速度有节省空间)
7、把虚拟内存也转到其他盘。 (最好就是将这些东西和平时临时下载文件放 在一个不大的分区里,这样也方便整理硬盘)
8、将应用软件装在其他盘(这对重装系统也有好处,可以省很多事)。

9、删除windowsime下不用的输入法! (日文,韩文,繁体中文输入 法,84.5MB) (到底哪个是哪个自己研究一下吧!有时候也要自己动动脑子 的,锻炼一下吧!)
10、如用ntfs装xp,本身就节省地盘。

注意:有些文件的删除可能有潜在的危险性,如果对windows了解不多请慎用 此法,如果出错的话本人盖不负责。(操作前请找到文件夹选项,将文件查看 选择为显示所有文件,显示受系统保护的文件,否则有些文件找不到)

 

转载于:https://www.cnblogs.com/freedom831215/archive/2010/10/20/1856891.html

已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符 “速评一下”
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页