数据库性能优化之SQL语句优化3

舒适提示:本篇内容均来自网上,本人只作了稍微处理,未进行细致研究,仅当作之后不备之需,如若你喜欢可尽情转走。 sql

查询速度慢的缘由: 数据库

一、没有索引或者没有用到索引(这是查询慢最多见的问题,是程序设计的缺陷) 
二、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下变得功能很强大,他的目的是支持循环。  
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(Fimage)   values   (@image),   在前台调用这个存储过程传入二进制参数,这样处理速度明显改善。  
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 post


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进行转化。一样字符和整型数据的转换。

相关文章
相关标签/搜索