50种方法优化SQL Server数据库查询(有N多错别字)
http://database.51cto.com/art/200612/35820.htm
查询速度慢的缘由不少,常见以下几种:
一、没有索引或者没有用到索引(这是查询慢最多见的问题,是程序设计的缺陷)
二、I/O吞吐量小,造成了瓶颈效应。
三、没有建立计算列致使查询不优化。
四、内存不足
五、网络速度慢
六、查询出的数据量过大(能够采用屡次查询,其余的方法下降数据量)
七、锁或者死锁(这也是查询慢最多见的问题,是程序设计的缺陷)
八、sp_lock,sp_who,活动的用户查看,缘由是读写竞争资源。
九、返回了没必要要的行和列
十、查询语句很差,没有优化
能够经过以下方法来优化查询 :
一、把数据、日志、索引放到不一样的I/O设备上,增长读取速度,之前能够将Tempdb应放在RAID0上,SQL2000不在支持。数据量(尺寸)越大,提升I/O越重要.
二、纵向、横向分割表,减小表的尺寸(sp_spaceuse)
三、升级硬件
四、根据查询条件,创建索引,优化索引、优化访问方式,限制结果集的数据量。注意填充因子要适当(最好是使用默认值0)。索引应该尽可能小,使用字节数小的列建索引好(参照索引的建立),不要对有限的几个值的字段建单一索引如性别字段
五、提升网速;
六、扩大服务器的内存,Windows 2000和SQL server 2000能支持4-8G的内存。配置虚拟内存:虚拟内存大小应基于计算机上并发运行的服务进行配置。运行 Microsoft SQL Server? 2000 时,可考虑将虚拟内存大小设置为计算机中安装的物理内存的 1.5 倍。若是另外安装了全文检索功能,并打算运行 Microsoft 搜索服务以便执行全文索引和查询,可考虑:将虚拟内存大小配置为至少是计算机中安装的物理内存的 3 倍。将 SQL Server max server memory 服务器配置选项配置为物理内存的 1.5 倍(虚拟内存大小设置的一半)。
七、增长服务器 CPU个数;可是必须明白并行处理串行处理更须要资源例如内存。使用并行仍是串行程是MsSQL自动评估选择的。单个任务分解成多个任务,就能够在处理器上运行。例如耽搁查询的排序、链接、扫描和GROUP BY字句同时执行,SQL SERVER根据系统的负载状况决定最优的并行等级,复杂的须要消耗大量的CPU的查询最适合并行处理。可是更新操做Update,Insert, Delete还不能并行处理。
八、若是是使用like进行查询的话,简单的使用index是不行的,可是全文索引,耗空间。 like 'a%' 使用索引 like '%a' 不使用索引用 like '%a%' 查询时,查询耗时和字段值总长度成正比,因此不能用CHAR类型,而是VARCHAR。对于字段的值很长的建全文索引。
九、DB Server 和APPLication Server 分离;OLTP和OLAP分离
十、分布式分区视图可用于实现数据库服务器联合体。联合体是一组分开管理的服务器,但它们相互协做分担系统的处理负荷。这种经过分区数据造成数据库服务器联合体的机制可以扩大一组服务器,以支持大型的多层 Web 站点的处理须要。有关更多信息,参见设计联合数据库服务器。(参照SQL帮助文件'分区视图')
a、在实现分区视图以前,必须先水平分区表
b、在建立成员表后,在每一个成员服务器上定义一个分布式分区视图,而且每一个视图具备相同的名称。这样,引用分布式分区视图名的查询能够在任何一个成员服务器上运行。系统操做如同每一个成员服务器上都有一个原始表的复本同样,但其实每一个服务器上只有一个成员表和一个分布式分区视图。数据的位置对应用程序是透明的。
十一、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收缩数据和日志 DBCC SHRINKDB,DBCC SHRINKFILE. 设置自动收缩日志.对于大的数据库不要设置数据库自动增加,它会下降服务器的性能。在T-sql的写法上有很大的讲究,下面列出常见的要点:首先, DBMS处理查询计划的过程是这样的:
一、 查询语句的词法、语法检查
二、 将语句提交给DBMS的查询优化器
三、 优化器作代数优化和存取路径的优化
四、 由预编译模块生成查询规划
五、 而后在合适的时间提交给系统处理执行
六、 最后将执行结果返回给用户其次,看一下SQL SERVER的数据存放的结构:一个页面的大小为8K(8060)字节,8个页面为一个盘区,按照B树存放。
十二、Commit和rollback的区别 Rollback:回滚全部的事物。 Commit:提交当前的事物. 没有必要在动态SQL里写事物,若是要写请写在外面如: begin tran exec(@s) commit trans 或者将动态SQL 写成函数或者存储过程。
1三、在查询Select语句中用Where字句限制返回的行数,避免表扫描,若是返回没必要要的数据,浪费了服务器的I/O资源,加剧了网络的负担下降性能。若是表很大,在表扫描的期间将表锁住,禁止其余的联接访问表,后果严重。
1四、SQL的注释申明对执行没有任何影响
1五、尽量不使用光标,它占用大量的资源。若是须要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 提示将使指定了该提示的表在游标内是只读的。
1六、用Profiler来跟踪查询,获得查询所需的时间,找出SQL的问题所在;用索引优化器优化索引
1七、注意UNion和UNion all 的区别。UNION all好
1八、注意使用DISTINCT,在没有必要时不要用,它同UNION同样会使查询变慢。重复的记录在查询里是没有问题的
1九、查询时不要返回不须要的行、列
20、用sp_configure 'query governor cost limit'或者SET QUERY_GOVERNOR_COST_LIMIT来限制查询消耗的资源。当评估查询消耗的资源超出限制时,服务器自动取消查询,在查询以前就扼杀掉。 SET LOCKTIME设置锁的时间
2一、用select top 100 / 10 Percent 来限制用户返回的行数或者SET ROWCOUNT来限制操做的行
2二、在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"能优化她,而"<>"等仍是不能优化,用不到索引。
2三、使用Query Analyzer,查看SQL语句的查询计划和评估分析是不是优化的SQL。通常的20%的代码占据了80%的资源,咱们优化的重点是这些慢的地方。
2四、若是使用了IN或者OR等时发现查询没有走索引,使用显示申明指定索引: Select * FROM PersonMember (INDEX = IX_Title) Where processid IN (男,'女)
2五、将须要查询的结果预先计算好放在表中,查询的时候再Select。这在SQL7.0之前是最重要的手段。例如医院的住院费计算。
2六、MIN() 和 MAX()能使用到合适的索引。
2七、数据库有一个原则是代码离数据越近越好,因此优先选择Default,依次为Rules,Triggers, Constraint(约束如外健主健CheckUNIQUE……,数据类型的最大长度等等都是约束),Procedure.这样不只维护工做小,编写程序质量高,而且执行的速度快。
2八、若是要插入大的二进制值到Image列,使用存储过程,千万不要用内嵌Insert来插入(不知JAVA是否)。由于这样应用程序首先将二进制值转换成字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值.存储过程就没有这些动做: 方法:Create procedure p_insert as insert into table(Fp_w_picpath) values (@p_w_picpath), 在前台调用这个存储过程传入二进制参数,这样处理速度明显改善。
2九、Between在某些时候比IN 速度更快,Between可以更快地根据索引找到范围。用查询优化器可见到差异。 select * from chineseresume where title in (男,女') Select * from chineseresume where between 男 and 女 是同样的。因为in会在比较屡次,因此有时会慢些。
30、在必要是对全局或者局部临时表建立索引,有时可以提升速度,但不是必定会这样,由于索引也耗费大量的资源。他的建立同是实际表同样。
3一、不要建没有做用的事物例如产生报表时,浪费资源。只有在必要使用事物时使用它。
3二、用OR的字句能够分解成多个查询,而且经过UNION 链接多个查询。他们的速度只同是否使用索引有关,若是查询须要用到联合索引,用UNION all执行的效率更高.多个OR的字句没有用到索引,改写成UNION的形式再试图与索引匹配。一个关键的问题是否用到索引。
3三、尽可能少用视图,它的效率低。对视图操做比直接对表操做慢,能够用stored procedure来代替她。特别的是不要用视图嵌套,嵌套视图增长了寻找原始资料的难度。咱们看视图的本质:它是存放在服务器上的被优化好了的已经产生了查询规划的SQL。对单个表检索数据时,不要使用指向多个表的视图,直接从表检索或者仅仅包含这个表的视图上读,不然增长了没必要要的开销,查询受到干扰.为了加快视图的查询,MsSQL增长了视图索引的功能。
3四、没有必要时不要用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
3五、在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减小判断的次数。
3六、当用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 也会锁系统表(无论是临时表仍是系统表)。因此千万不要在事物内使用它!!!这样的话若是是常常要用的临时表请使用实表,或者临时表变量。
3七、通常在GROUP BY 个HAVING字句以前就能剔除多余的行,因此尽可能不要用它们来作剔除行的工做。他们的执行顺序应该以下最优:select 的Where字句选择全部合适的行,Group By用来分组个统计行,Having字句用来剔除多余的分组。这样Group By 个Having的开销小,查询快.对于大的数据行进行分组和Having十分消耗资源。若是Group BY的目的不包括计算,只是分组,那么用Distinct更快
3八、一次更新多条记录比分屡次更新每次一条快,就是说批处理好
3九、少用临时表,尽可能用结果集和Table类性的变量来代替它,Table 类型的变量比临时表好
40、在SQL2000下,计算字段是能够索引的,须要知足的条件以下:
a、计算字段的表达是肯定的
b、不能用在TEXT,Ntext,Image数据类型
c、必须配制以下选项 ANSI_NULLS = ON, ANSI_PADDINGS = ON, …….
4一、尽可能将数据的处理工做放在服务器上,减小网络的开销,如使用存储过程。存储过程是编译好、优化过、而且被组织到一个执行规划里、且存储在数据库中的SQL语句,是控制流语言的集合,速度固然快。反复执行的动态SQL,可使用临时存储过程,该过程(临时表)被放在Tempdb中。之前因为SQL SERVER对复杂的数学计算不支持,因此不得不将这个工做放在其余的层上而增长网络的开销。SQL2000支持UDFs,如今支持复杂的数学计算,函数的返回值不要太大,这样的开销很大。用户自定义函数象光标同样执行的消耗大量的资源,若是返回大的结果采用存储过程
4二、不要在一句话里再三的使用相同的函数,浪费资源,将结果放在变量里再调用更快
4三、Select COUNT(*)的效率教低,尽可能变通他的写法,而EXISTS快.同时请注意区别: select count(Field of null) from Table 和 select count(Field of NOT null) from Table 的返回值是不一样的!!!
4四、当服务器的内存够多时,配制线程数量 = 最大链接数+5,这样能发挥最大的效率;不然使用 配制线程数量<最大链接数启用SQL SERVER的线程池来解决,若是仍是数量 = 最大链接数+5,严重的损害服务器的性能。
4五、按照必定的次序来访问你的表。若是你先锁住表A,再锁住表B,那么在全部的存储过程当中都要按照这个顺序来锁定它们。若是你(不经意的)某个存储过程当中先锁定表B,再锁定表A,这可能就会致使一个死锁。若是锁定顺序没有被预先详细的设计好,死锁很难被发现
4六、经过SQL Server Performance Monitor监视相应硬件的负载 Memory: Page Faults / sec计数器若是该值偶尔走高,代表当时有线程竞争内存。若是持续很高,则内存多是瓶颈。
Process:
一、% DPC Time 指在范例间隔期间处理器用在缓延程序调用(DPC)接收和提供服务的百分比。(DPC 正在运行的为比标准间隔优先权低的间隔)。 因为 DPC 是以特权模式执行的,DPC 时间的百分比为特权时间百分比的一部分。这些时间单独计算而且不属于间隔计算总数的一部 分。这个总数显示了做为实例时间百分比的平均忙时。
二、%Processor Time计数器 若是该参数值持续超过95%,代表瓶颈是CPU。能够考虑增长一个处理器或换一个更快的处理器。
三、% Privileged Time 指非闲置处理器时间用于特权模式的百分比。(特权模式是为操做系统组件和操纵硬件驱动程序而设计的一种处理模式。它容许直接访问硬件和全部内存。另外一种模式为用户模式,它是一种为应用程序、环境分系统和整数分系统设计的一种有限处理模式。操做系统将应用程序线程转换成特权模式以访问操做系统服务)。特权时间的 % 包括为间断和 DPC 提供服务的时间。特权时间比率高多是因为失败设备产生的大数量的间隔而引发的。这个计数器将平均忙时做为样本时间的一部分显示。
四、% User Time表示耗费CPU的数据库操做,如排序,执行aggregate functions等。若是该值很高,可考虑增长索引,尽可能使用简单的表联接,水平分割大表格等方法来下降该值。 Physical Disk: Curretn Disk Queue Length计数器该值应不超过磁盘数的1.5~2倍。要提升性能,可增长磁盘。 SQLServer:Cache Hit Ratio计数器该值越高越好。若是持续低于80%,应考虑增长内存。 注意该参数值是从SQL Server启动后,就一直累加记数,因此运行通过一段时间后,该值将不能反映系统当前值。
4七、分析select emp_name form employee where salary > 3000 在此语句中若salary是Float类型的,则优化器对其进行优化为Convert(float,3000),由于3000是个整数,咱们应在编程时使用3000.0而不要等运行时让DBMS进行转化。一样字符和整型数据的转换。
4八、查询的关联同写的顺序
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 = '号码')
4九、
(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:网页教学网
1、适合读者对象:数据库开发程序员,数据库的数据量不少,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。
2、介绍:在数据库的开发过程当中,常常会遇到复杂的业务逻辑和对数据库的操做,这个时候就会用SP来封装数据库操做。若是项目的SP较多,书写又没有必定的规范,将会影响之后的系统维护困难和大SP逻辑的难以理解,另外若是数据库的数据量大或者项目对SP 的性能要求很,就会遇到优化的问题,不然速度有可能很慢,通过亲身经验,一个通过优化过的SP要比一个性能差的SP的效率甚至高几百倍。
3、内容:
一、开发人员若是用到其余库的Table或View,务必在当前库中创建View来实现跨库操做,最好不要直接使用“databse.dbo.table_name”,由于sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。
二、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,作过自身的查询优化检查。
三、高程序运行效率,优化应用程序,在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 等。
解析:Microsoft SQL Server中的锁模式
在SQL Server数据库中加锁时,除了能够对不一样的资源加锁,还可使用不一样程度的加锁方式,即锁有多种模式,SQL Server中锁模式包括:
1.共享锁 SQL Server中,共享锁用于全部的只读数据操做。共享锁是非独占的,容许多个并发事务读取其锁定的资源。默认状况下,数据被读取后,SQL Server当即释放共享锁。例如,执行查询“SELECT * FROM AUTHORS”时,首先锁定第一页,读取以后,释放对第一页的锁定,而后锁定第二页。这样,就容许在读操做过程当中,修改未被锁定的第一页。可是,事务隔离级别链接选项设置和SELECT语句中的锁定设置均可以改变SQL Server的这种默认设置。例如,“ SELECT * FROM AUTHORS HOLDLOCK”就要求在整个查询过程当中,保持对表的锁定,直到查询完成才释放锁定。
2.更新锁更新锁在修改操做的初始化阶段用来锁定可能要被修改的资源,这样能够避免使用共享锁形成的死锁现象。由于使用共享锁时,修改数据的操做分为两步,首先得到一个共享锁,读取数据,而后将共享锁升级为排它锁,而后再执行修改操做。这样若是同时有两个或多个事务同时对一个事务申请了共享锁,在修改数据的时候,这些事务都要将共享锁升级为排它锁。这时,这些事务都不会释放共享锁而是一直等待对方释放,这样就形成了死锁。若是一个数据在修改前直接申请更新锁,在数据修改的时候再升级为排它锁,就能够避免死锁。
3.排它锁 排它锁是为修改数据而保留的。它所锁定的资源,其余事务不能读取也不能修改。
4.结构锁 执行表的数据定义语言 (DDL) 操做(例如添加列或除去表)时使用架构修改 (Sch-M) 锁。当编译查询时,使用架构稳定性 (Sch-S) 锁。架构稳定性 (Sch-S) 锁不阻塞任何事务锁,包括排它锁。所以在编译查询时,其它事务(包括在表上有排它锁的事务)都能继续运行。但不能在表上执行 DDL 操做。
5.意向锁 意向锁说明SQL Server有在资源的低层得到共享锁或排它锁的意向。例如,表级的共享意向锁说明事务意图将排它锁释放到表中的页或者行。意向锁又能够分为共享意向锁、独占意向锁和共享式独占意向锁。共享意向锁说明事务意图在共享意向锁所锁定的低层资源上放置共享锁来读取数据。独占意向锁说明事务意图在共享意向锁所锁定的低层资源上放置排它锁来修改数据。共享式排它锁说明事务容许其余事务使用共享锁来读取顶层资源,并意图在该资源低层上放置排它锁。
6.大容量更新锁 当将数据大容量复制到表,且指定了 TABLOCK 提示或者使用 sp_tableoption 设置了 table lock on bulk 表选项时,将使用大容量更新锁。大容量更新锁容许进程将数据并发地大容量复制到同一表,同时防止其它不进行大容量复制数据的进程访问该表。
详细介绍优化SQL Server 2000的设置
SQL Server已经为了优化本身的性能而进行了良好的配置,比今天市场其余的关系型数据库都要好得多。然而,你仍然有几项设置须要进行修改,以便你的数据库每分钟能够处理更多的事务(TPM)。本篇文章的目的就是讨论这些设置。咱们忽略那些能够经过硬件配置或者表或者索引设计提升的性能,由于这些内容在本篇文章范围以外。
破碎页面检测
在咱们开始讨论服务器配置开关以前,让咱们快速浏览一下你的模型数据库--或者说用做构建新的数据库的基础的模板。默认状况下,你能够在数据库中建立存储过程、函数等相似的东西,随后他们将会被加入新建立的数据库中。
要优化性能,你也许想要关闭模型数据库中的破碎页面检测。当一个页面被成功写入磁盘的时候,破碎页面检测进行识别。若是激活了的话,你能够看到每一个写操做对性能产生的每一个细小的影响。大多数现代的磁盘阵列都有板上电池,使得阵列能够在忽然断电的状况下完成全部的写操做--引发破碎页面的最频繁缘由。
如下的步骤能够接受如何关闭破碎页面检测:
exec sp_dboption 'model', 'torn page detection', 'false'
这篇基础知识资源能够为你提供更多有关这个设置的信息。
大多数的配置是经过系统存储过程sp_configure完成的。要显示服务器的所有设置列表以便定制,你能够输入以下命令:
sp_configure 'show advanced options', 1
GO
RECONFIGURE WITH OVERRIDE
你能够配置的选项的数量根据你的SQL Server的版本、服务包,以及位数版本(64位的SQL Server比32位的选项要多)而定。我将直接讨论最能影响SQL Server性能优化的选项。
Affinity mask: Affinity mask让你能够控制SQL Server使用哪一个处理器。对于大多数状况,你不该该接触这个设置,让操做系统控制处理器关系。然而,你也许想要用这个选项来将某个处理器专门用于另外一个进程(例如,MSSearch 或者 SQL Server磁盘 IO ,以及 SQL Server的平衡)。参考基础知识资源获取更多有关这个设置的信息。
Awe enabled: Awe的启动可让SQL Server Enterprise版本运行在Windows 2000以及以上高级服务器上,或者Windows 2003 Enterprise以及以上的版本使用超过4GB的内存。若是你的服务器符合这些条件的话,就激活这个设置吧。
并行成本极限:当查询须要进行并行处理的时候,并行的成本极限就定下来了。默认状况是五秒钟。将这个数值改成稍低的数值,俄可让更多个查询得到并行处理,可是这也会引发CPU瓶颈。这个设置只有在多个处理器的机器上才会起做用。
填充因子:填充因子设置了在建立聚簇索引的时候用来自动填充的因子。在频繁插入的表中,将数值从默认的90%设置为较低的数值,你会得到收益。
轻量级缓冲池:这个设置启动了光纤模式。使用这个选项在CPU利用率很高的8路及其以上的服务器上。这可让光纤同时为每一个线程提供服务,同时在默认状况下运行在每一个处理器上。某些任务能够从这些光纤中得到优点。
并行的最大程度:当服务器可使用并行或者不能使用并行,或者是当某个数量的处理器能够用于并行操做的时候,这个设置就肯定了。并行就是多个处理器上发生多个处理。例如,查询的并行操做能够在不一样的处理器上同时处理。
服务器最大内存(MB):若是你在SQL Server上运行了其余的处理,而且有足够的内存,那么你有可能想要留出512MB的内存给操做系统和这些进程。例如,你能够在MSSearch或者在本地运行大量的代理的状况下将其设置为512。
最大工做线程:最大工做线程设置与ADO.net中的链接池有些相似。经过这个设置,任何超过限制(255个用户)的用户链接均可以在线程池中等待,直到为某个链接服务的线程获得释放,就好像是ADO.net中的链接与链接池共享。若是你有很大量的链接,而且大量的内存,那么你就能够提升这个数值。
网络包尺寸(B):这个设置控制了网络中传输到你的客户端的包的尺寸。在有损耗的网络中(例如电话线),你可能想要将这个参数设置为比较低的数值,墨人数值是4096。在链接良好的网络中,你能够提升这个设置,特别是涉及BLOB的大型批处理操做。
优先推动:这个设置为SQL Server提供了处理器的推进。在任务管理器中,点击进程标签,定位SQL Server的位置,而后右击它。选择“设置优先级别”。注意,SQL Server应该运行在正常的优先级别上。输入以下命令:
Sp_configure 'priority boost', 1
Reconfigure with override
而后从新启动你的SQL Server。在任务管理器中察看SQL Server如今运行在什么优先级别上。它应该是在高优先级上。SQL Server应该比其余的用户进程运行优先级别要高。在专用于SQL Server的服务器上使用这个设置。
总结
本篇讨论了最多见的SQL Server优化设置。在作出改变以前和以后分别在测试环境中进行基线肯定是很是重要的,能够据此来评估在典型的负载下,改变对你的系统的影响。
SQL Server 数据库中关于死锁的分析
SQL Server数据库发生死锁时不会像ORACLE那样自动生成一个跟踪文件。有时能够在[管理]->[当前活动] 里看到阻塞信息(有时SQL Server企业管理器会由于锁太多而没有响应).
设定跟踪1204:
USE MASTER
DBCC TRACEON (1204,-1)
显示当前启用的全部跟踪标记的状态:
DBCC TRACESTATUS(-1)
取消跟踪1204:
DBCC TRACEOFF (1204,-1)
在设定跟踪1204后,会在数据库的日志文件里显示SQL Server数据库死锁时一些信息。但那些信息很难看懂,须要对照SQL Server联机丛书仔细来看。根据PAG锁要找到相关数据库表的方法:
DBCC TRACEON (3604)
DBCC PAGE (db_id,file_id,page_no)
DBCC TRACEOFF (3604)
请参考sqlservercentral.com上更详细的讲解.但又从CSDN学到了一个找到死锁缘由的方法。我稍加修改, 去掉了游标操做并增长了一些提示信息,写了一个系统存储过程sp_who_lock.sql。代码以下:
if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[sp_who_lock]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[sp_who_lock]
GO
/********************************************************
// 建立 : fengyu 邮件 : maggiefengyu@tom.com
// 日期 :2004-04-30
// 修改 : 从http://www.csdn.net/develop/Read_Article.asp?id=26566
// 学习到并改写
// 说明 : 查看数据库里阻塞和死锁状况
********************************************************/
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 (@bl )
end
-- 循环指针下移
set @intCounter = @intCounter + 1
end
drop table #tmp_lock_who
return 0
end
须要的时候直接调用:
sp_who_lock
就能够查出引发死锁的进程和SQL语句.
SQL Server自带的系统存储过程sp_who和sp_lock也能够用来查找阻塞和死锁, 但没有这里介绍的方法好用。若是想知道其它tracenum参数的含义,请看www.sqlservercentral.com文章
咱们还能够设置锁的超时时间(单位是毫秒), 来缩短死锁可能影响的时间范围:
例如:
use master
seelct @@lock_timeout
set lock_timeout 900000
-- 15分钟
seelct @@lock_timeout
优化SQLServer索引的小技巧
SQL Server中有几个可让你检测、调整和优化SQL Server性能的工具。在本文中,我将说明如何用SQL Server的工具来优化数据库索引的使用,本文还涉及到有关索引的通常性知识。
关于索引的常识
影响到数据库性能的最大因素就是索引。因为该问题的复杂性,我只可能简单的谈谈这个问题,不过关于这方面的问题,目前有好几本不错的书籍可供你参阅。我在这里只讨论两种SQL Server索引,即clustered索引和nonclustered索引。当考察创建什么类型的索引时,你应当考虑数据类型和保存这些数据的 column。一样,你也必须考虑数据库可能用到的查询类型以及使用的最为频繁的查询类型。
索引的类型
若是column保存了高度相关的数据,而且经常被顺序访问时,最好使用clustered索引,这是由于若是使用clustered索引,SQL Server会在物理上按升序(默认)或者降序重排数据列,这样就能够迅速的找到被查询的数据。一样,在搜寻控制在必定范围内的状况下,对这些 column也最好使用clustered索引。这是由于因为物理上重排数据,每一个表格上只有一个clustered索引。
与上面状况相反,若是columns包含的数据相关性较差,你可使用nonculstered索引。你能够在一个表格中使用高达249个nonclustered索引--尽管我想象不出实际应用场合会用的上这么多索引。
当表格使用主关键字(primary keys),默认状况下SQL Server会自动对包含该关键字的column(s)创建一个独有的cluster索引。很显然,对这些column(s)创建独有索引意味着主关键字的惟一性。当创建外关键字(foreign key)关系时,若是你打算频繁使用它,那么在外关键字cloumn上创建nonclustered索引不失为一个好的方法。若是表格有 clustered索引,那么它用一个链表来维护数据页之间的关系。相反,若是表格没有clustered索引,SQL Server将在一个堆栈中保存数据页。
数据页
当索引创建起来的时候,SQLServer就创建数据页(datapage),数据页是用以加速搜索的指针。当索引创建起来的时候,其对应的填充因子也即被设置。设置填充因子的目的是为了指示该索引中数据页的百分比。随着时间的推移,数据库的更新会消耗掉已有的空闲空间,这就会致使页被拆分。页拆分的后果是下降了索引的性能,于是使用该索引的查询会致使数据存储的支离破碎。当创建一个索引时,该索引的填充因子即被设置好了,所以填充因子不能动态维护。
为了更新数据页中的填充因子,咱们能够中止旧有索引并重建索引,并从新设置填充因子(注意:这将影响到当前数据库的运行,在重要场合请谨慎使用)。 DBCC INDEXDEFRAG和DBCC DBREINDEX是清除clustered和nonculstered索引碎片的两个命令。INDEXDEFRAG是一种在线操做(也就是说,它不会阻塞其它表格动做,如查询),而DBREINDEX则在物理上重建索引。在绝大多数状况下,重建索引能够更好的消除碎片,可是这个优势是以阻塞当前发生在该索引所在表格上其它动做为代价换取来得。当出现较大的碎片索引时,INDEXDEFRAG会花上一段比较长的时间,这是由于该命令的运行是基于小的交互块(transactional block)。
填充因子
当你执行上述措施中的任何一个,数据库引擎能够更有效的返回编入索引的数据。关于填充因子(fillfactor)话题已经超出了本文的范畴,不过我仍是提醒你须要注意那些打算使用填充因子创建索引的表格。
在执行查询时,SQL Server动态选择使用哪一个索引。为此,SQL Server根据每一个索引上分布在该关键字上的统计量来决定使用哪一个索引。值得注意的是,通过平常的数据库活动(如插入、删除和更新表格),SQL Server用到的这些统计量可能已经“过时”了,须要更新。你能够经过执行DBCC SHOWCONTIG来查看统计量的状态。当你认为统计量已经“过时”时,你能够执行该表格的UPDATE STATISTICS命令,这样SQL Server就刷新了关于该索引的信息了。
创建数据库维护计划
SQL Server提供了一种简化并自动维护数据库的工具。这个称之为数据库维护计划向导(Database Maintenance Plan Wizard ,DMPW)的工具也包括了对索引的优化。若是你运行这个向导,你会看到关于数据库中关于索引的统计量,这些统计量做为日志工做并定时更新,这样就减轻了手工重建索引所带来的工做量。若是你不想自动按期刷新索引统计量,你还能够在DMPW中选择从新组织数据和数据页,这将中止旧有索引并按特定的填充因子重建索引。
Sybase SQL Server索引的使用和优化
在应用系统中,尤为在联机事务处理系统中,对数据查询及处理速度已成为衡 量应用系统成败的标准。而采用索引来加快数据处理速度也成为广大数据库用户所 接受的优化方法。
在良好的数据库设计基础上,能有效地使用索引是SQL Server取得高性能的基础,SQL Server采用基于代价的优化模型,它对每个提交的有关表的查询,决定是否使用索引或用哪个索引。由于查询执行的大部分开销是磁盘I/O,使用索引提升性能的一个主要目标是避免全表扫描,由于全表扫描须要从磁盘上读表的每个数据页,若是有索引指向数据值,则查询只需读几回磁盘就能够了。因此若是创建了合理的索引,优化器就能利用索引加速数据的查询过程。可是,索引并不老是提升系统的性能,在增、删、改操做中索引的存在会增长必定的工做量,所以,在适当的地方增长适当的索引并从不合理的地方删除次优的索引,将有助于优化那些性能较差的SQL Server应用。实践代表,合理的索引设计是创建在对各类查询的分析和预测上的,只有正确地使索引与程序结合起来,才能产生最佳的优化方案。本文就SQL Server索引的性能问题进行了一些分析和实践。
1、聚簇索引(clustered indexes)的使用
聚簇索引是一种对磁盘上实际数据从新组织以按指定的一个或多个列的值排序。因为聚簇索引的索引页面指针指向数据页面,因此使用聚簇索引查找数据几乎老是比使用非聚簇索引快。每张表只能建一个聚簇索引,而且建聚簇索引须要至少至关该表120%的附加空间,以存放该表的副本和索引中间页。创建聚簇索引的思想是:
一、 大多数表都应该有聚簇索引或使用分区来下降对表尾页的竞争,在一个高事务的环境中,对最后一页的封锁严重影响系统的吞吐量。
二、在聚簇索引下,数据在物理上按顺序排在数据页上,重复值也排在一块儿,于是在那些包含范围检查(between、<、<=、>、> =)或使用group by或order by的查询时,一旦找到具备范围中第一个键值的行,具备后续索引值的行保证物理上毗连在一块儿而没必要进一步搜索,避免了大范围扫描,能够大大提升查询速度。
三、 在一个频繁发生插入操做的表上创建聚簇索引时,不要建在具备单调上升值的列(如IDENTITY)上,不然会常常引发封锁冲突。
四、 在聚簇索引中不要包含常常修改的列,由于码值修改后,数据行必须移动到新的位置。
五、 选择聚簇索引应基于where子句和链接操做的类型。聚簇索引的侯选列是:
● 主键列,该列在where子句中使用而且插入是随机的。
● 按范围存取的列,如pri_order > 100 and pri_order < 200 。
● 在group by或order by中使用的列。
● 不常常修改的列。
● 在链接操做中使用的列。
2、非聚簇索引(nonclustered indexes)的使用
SQL Server缺省状况下创建的索引是非聚簇索引,因为非聚簇索引不从新组织表中的数据,而是对每一行存储索引列值并用一个指针指向数据所在的页面。换句话说非聚簇索引具备在索引结构和数据自己之间的一个额外级。一个表若是没有聚簇索引时,可有250个非聚簇索引。每一个非聚簇索引提供访问数据的不一样排序顺序。在创建非聚簇索引时,要权衡索引对查询速度的加快与下降修改速度之间的利弊。另外,还要考虑这些问题:
● 索引须要使用多少空间。
● 合适的列是否稳定。
● 索引键是如何选择的,扫描效果是否更佳。
● 是否有许多重复值。
对更新频繁的表来讲,表上的非聚簇索引比聚簇索引和根本没有索引须要更多的额外开销。对移到新页的每一行而言,指向该数据的每一个非聚簇索引的页级行也必须更新,有时可能还须要索引页的分理。从一个页面删除数据的进程也会有相似的开销,另外,删除进程还必须把数据移到页面上部,以保证数据的连续性。因此,创建非聚簇索引要很是慎重。非聚簇索引常被用在如下状况:
● 某列经常使用于集合函数(如Sum,....)。
● 某列经常使用于join,order by,group by。
● 查寻出的数据不超过表中数据量的20%。
3、覆盖索引(covering indexes)的使用
覆盖索引是指那些索引项中包含查寻所须要的所有信息的非聚簇索引,这 种索引之因此比较快也正是由于索引页中包含了查寻所必须的数据,不需去访 问数据页。 若是非聚簇索引中包含结果数据,那么它的查询速度将快于聚簇索引。
可是因为覆盖索引的索引项比较多,要占用比较大的空间。并且update 操 做会引发索引值改变。因此若是潜在的覆盖查询并不经常使用或不太关键,则覆盖索引的增长反而会下降性能。
4、索引的选择技术
p_detail是住房公积金管理系统中记录我的明细的表,有890000行,观察在不一样索引下的查询运行效果,测试在C/S环境下进行,客户机是 IBM PII350(内存64M),服务器是DEC Alpha1000A(内存128M),数据库为SYBASE11.0.3。
一、 select count(*) from p_detail where op_date>’19990101’ and op_date<’19991231’ and pri_surplus1>300
二、 select count(*),sum(pri_surplus1) from p_detail where op_date>’19990101’ and pay_month between ‘199908’ and ’199912’
不建任何索引 查询1 1分15秒
查询2 1分7秒
在op_date上建非聚簇索引 查询1 57秒
查询2 57秒
在op_date上建聚簇索引 查询1 <1秒
查询2 52秒
在pay_month、op_date、pri_surplus1上建索引 查询1 34秒
查询2 <1秒
在op_date、pay_month、pri_surplus1上建索引 查询1 <1秒
查询2 <1秒
从以上查询效果分析,索引的有无,创建方式的不一样将会致使不一样的查询效果,选择什么样的索引基于用户对数据的查询条件,这些条件体现于where从句和join表达式中。通常来讲创建索引的思路是:
(1)、主键时常做为where子句的条件,应在表的主键列上创建聚簇索引,尤为当常常用它做为链接的时候。
(2)、有大量重复值且常常有范围查询和排序、分组发生的列,或者很是频繁地被访问的列,可考虑创建聚簇索引。
(3)、常常同时存取多列,且每列都含有重复值可考虑创建复合索引来覆盖一个或一组查询,并把查询引用最频繁的列做为前导列,若是可能尽可能使关键查询造成覆盖查询。
(4)、若是知道索引键的全部值都是惟一的,那么确保把索引定义成惟一索引。
(5)、在一个常常作插入操做的表上建索引时,使用fillfactor(填充因子)来减小页分裂,同时提升并发度下降死锁的发生。若是在只读表上建索引,则能够把fillfactor置为100。
(6)、在选择索引键时,设法选择那些采用小数据类型的列做为键以使每一个索
引页可以容纳尽量多的索引键和指针,经过这种方式,可以使一个查询必须遍历的索引页面降到最小。此外,尽量地使用整数为键值,由于它可以提供比任何数据类型都快的访问速度。
5、索引的维护
上面讲到,某些不合适的索引影响到SQL Server的性能,随着应用系统的运行,数据不断地发生变化,当数据变化达到某一个程度时将 会影响到索引的使用。这时 须要用户本身来维护索引。索引的维护包括:
一、重建索引
随着数据行的插入、删除和数据页的分裂,有些索引页可能只包含几页数据,另外应用在执行大块I/O的时候,重建非聚簇索引能够下降分片,维护大块I/O的效率。重建索引其实是从新组织B-树空间。在下面状况下须要重建索引:
(1)、数据和使用模式大幅度变化。
(2)、排序的顺序发生改变。
(3)、要进行大量插入操做或已经完成。
(4)、使用大块I/O的查询的磁盘读次数比预料的要多。
(5)、因为大量数据修改,使得数据页和索引页没有充分使用而致使空间的使用超出估算。
(6)、dbcc检查出索引有问题。
当重建聚簇索引时,这张表的全部非聚簇索引将被重
建.
二、索引统计信息的更新
当在一个包含数据的表上建立索引的时候,SQL Server会建立分布数据页来存放有关索引的两种统计信息:分布表和密度表。优化器利用这个页来判断该索引对某个特定查询是否有用。但这个统计信息并不动态地从新计算。这意味着,当表的数据改变以后,统计信息有多是过期的,从而影响优化器追求最有工做的目标。所以,在下面状况下应该运行update statistics命令:
(1)、数据行的插入和删除修改了数据的分布。
(2)、对用truncate table删除数据的表上增长数据行。
(3)、修改索引列的值。
6、结束语
实践代表,不恰当的索引不但于事无补,反而会下降系统的执行性能。由于大量的索引在插入、修改和删除操做时比没有索引花费更多的系统时间。例以下面状况下创建的索引是不恰当的:
● 在查询中不多或从不引用的列不会受益于索引,由于索引不多或历来没必要搜索基于这些列的行。
● 只有两个或三个值的列,如男性和女性(是或否),从不会从索引中获得好处。
另外,鉴于索引加快了查询速度,但减慢了数据更新速度的特色。可经过在一个段上建表,而在另外一个段上建其非聚簇索引,而这两段分别在单独的物理设备上来改善操做性能。