SQL数据库优化及SQL语句使用_第1页
SQL数据库优化及SQL语句使用_第2页
SQL数据库优化及SQL语句使用_第3页
SQL数据库优化及SQL语句使用_第4页
SQL数据库优化及SQL语句使用_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

SQL数据库优化及SQL语句使用

二、据库语句优化

SQL语句优化的原则:

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

缺省情况下建立的索引是非群集索引,但有时它并不是最佳的。在非群集

索引下,数据在物理上随机存放在数据页上。合理的索引设计要建立在对各种

查询的分析和预测上。一般来说:①.有大量重复值、且经常有范围查询

(between,,,=,=)和orderby、groupby发生的列,可考虑建立群集索引;②.

经常同时存取多列,且每列都含有重复值可考虑建立组合索引;③.组合索引要

尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。索引虽有助

于提高性能但不是索引越多越好,恰好相反过多的索引会导致系统低效。用户

在表中每加进一个索引,维护索引集合就要做相应的更新工作。

♦2、ISNULL与ISNOTNULL

不能用null作索引,任何包含null值的列都将不会被包含在索引中。即

使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引

中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任

何在where子句中使用isnull或isnotnull的语句优化器是不允许使用索

引的。

♦3、IN和EXISTSEXISTS要远比IN的效率高。里面关系到fulltable

scan和rangescan。几乎将所有的IN操作符子查询改写为使用EXISTS的子查

询。

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

♦5、当在SQLSERVER2000中,如果存储过程只有一个参数,并且是

OUTPUT类型的,必须在调用这个存储过程的时候给这个参数一个初始的值,否

则会出现调用错误。

♦6、ORDERBY和GROPUBY

使用ORDERBY和GROUPBY短语,任何一种索引都有助于SELECT的性能提

高。注意如果索引列里面有NULL值,Optimizer将无法优化。

♦7、任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等

等,查询时要尽可能将操作移至等号右边。

♦8、IN、OR子句常会使用工作表,使索引失效。如果不产生大量重复值,

可以考虑把子句拆开。拆开的子句中应该包含索引。

♦9、SETSHOWPLAN_ALLON查看执行方案。DBCC检查数据库数据完整性。

DBCC(DataBaseConsistencyChecker)是一组用于验证SQLServer数据库

完整性的程序。

♦10、慎用游标

在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,

再对临时表定义游标进行操作,这样可使性能得到明显提高。

一些常用的SQL语句供大家参考,希望对大家有所帮助。

说明:存储过程的使用,CREATEPROC创建存储过程,SQL2000中用sp_xxx

和xp_xxx存储过程;一般来说,sp_xxx是一般的存储过程,而xp_xxx是扩展的

存储过程。使用这些系统存储过程时,一般使用USEMASTER然后在使用

sp_xxx或者xp_xxxo

说明:复制表(只复制结构,源表名:a新表名:b)

SQL:select*intobfromawhere11

说明:拷贝表(拷贝数据,源表名:a目标表名:b)

SQL:insertintob(a,b,c)selectd,e,ffromb;

说明:显示文章、提交人和最后回复时间

SQL:selecta.title,a.username,b.adddatefromtablea,(select

max(adddate)adddatefromtablewheretable.title=a.title)b

说明:外连接查询(表名1:a表名2:b)

SQL:selecta.a,a.b,a.c,b.c,b.d,b.ffromaLEFTOUTJOINbON

a.a=b.c

说明:日程安排提前五分钟提醒

SQL:select*from日程安排wheredatediff('minute',f开始时

间,getdate())5

说明:两张关联表,删除主表中已经在副表中没有的信息

SQL:

deletefrominfowherenotexists(select*frominfobzwhere

info.infid=infobz.infid

说明:一

SQL:

SELECTA.NUM,A.NAME,B.UPD_DATE,B.PREV_UPD_DATEFROMTABLEI,

(SELECTX.NUM,X.UPD_DATE,Y.UPD_DATEPREV_UPD_DATEFROM(SELECT

NUM,UPD„DATE,INBOUND_QTY,STOCK__ONHANDFROMTABLE2WHERE

TO_CHAR(UPD_DATE,'YYYY/MM')=TO_CHAR(SYSDATE,'YYYY/MM'))X,

(SELECTNUM,UPD-DATE,STOCK_ONHANDFROMTABLE2WHERE

TO_CHAR(UPD_DATE,'YYYY/MM')=

TO_CHAR(TO_DATE(TO_CHAR(SYSDATE,'YYYY/MM')'/01','YYYY/MM/DD")-

1,'YYYY/MM')Y,

WHEREX.NUM=Y.NUM(+)

ANDX.INBOUND_QTY+NVL(Y.STOCK_ONHAND,0)X.STOCK_ONHANDB

WHEREA.NUM=B.NUM

说明:一

SQL:

select*fromstudentinfowherenotexists(select*fromstudent

wherestudentinfo.id=student.id)and系名称='"&strdepartmentname&"'and

专业名称='"&strprofessionname&"'orderby性别,生源地,高考总成绩

说明:

从数据库中去一年的各单位电话费统计(电话费定额贺电化肥清单两个表来

源)

SQL:

SELECTa.userper,a.tel,a.standfee,TO_CHAR(a.telfeedate,'yyyy')AS

telyear,

SUM(decode(T0_CHAR(a.telfeedate,'mm'),'OT,a.factration))ASJAN,

SUM(decode(TO_CHAR(a.telfeedate,,mm,),502,,a.factration))ASFRI,

SUM(decode(TO_CHAR(a.telfeedate,5mm,),,03,,a.factration))ASMAR,

SUM(decode(T0_CHAR(a.telfeedate,'mm'),’04',a.factration))ASAPR,

SUM(decode(T0_CHAR(a.telfeedate,5mm,),'05',a.factration))ASMAY,

SUM(decode(TO_CHAR(a.telfeedate,5mm,'06',a.factration))ASJUE,

SUM(decode(T0_CHAR(a.telfeedate,5mm,),507',a.factration))ASJUL,

SUM(decode(T0_CHAR(a.telfeedate,?mm,),'08',a.factration))ASAGU,

SUM(decode(T0_CHAR(a.telfeedate,'mm'),’09,,a.factration))ASSEP,

SUM(decode(T0_CHAR(a.telfeedate,Jmm'),'10',a.factration))ASOCT,

SUM(decode(T0_CHAR(a.telfeedate,5mm,),?1T,a.factration))ASNOV,

SUM(decode(T0_CHAR(a.telfeedate,'mm'),'12',a.factration))ASDEC

FROM(SELECTa.userper,a.tel,a.standfee,b.telfeedate,b.factrationFROM

TELFEESTANDa,TELFEEb

WHEREa.tel=b.telfax)aGROUPBY

a.userper,a.tel,a.standfee,T0_CHAR(a.telfeedate,Jyyyy')

说明:四表联查问题:

SQL:select*fromaleftinnerjoinbona.a=b.brightinnerjoin

cona.a=c.cinnerjoindona.a=d.dwhere.

说明:得到表中最小的未使用的ID号

SQL:

SELECT(CASEWHENEXISTS(SELECT*FROMHandlebWHERE

b.HandleID=l)THENMIN(HandleID)+lELSE1END)asHandlelDFROMHandle

WHERENOTHandlelDIN(SELECTa.HandleID-1FROMHandlea)

三、数据库优化

1、索引问题

在做性能跟踪分析过程中,经常发现有不少后台程序的性能问题是因为缺

少合适索引造成的,有些表甚至一个索引都没有。这种情况往往都是因为在设

计表时,没去定义索引,而开发初期,由于表记录很少,索引创建与否,可能

对性能没啥影响,开发人员因此也未多加重视。然一旦程序发布到生产环境,

随着时间的推移,表记录越来越多,这时缺少索引,对性能的影响便会越来越

大了。

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

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

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

♦避免在索引字段上使用not,,!=

♦避免在索引列上使用ISNULL和ISNOTNULL

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

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

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

2、在可以使用UNIONALL的语句里,使用了UNIONUNION因为会将各查询

子集的记录做比较,故比起UNIONALL,通常速度都会慢上许多。一般来说,

如果使用UNIONALL能满足要求的话,务必使用UNIONALL。还有一种情况大

家可能会忽略掉,就是虽然要求几个子集的并集需要过滤掉重复记录,但由于

脚本的特殊性,不可能存在重复记录,这时便应该使用UNIONALL,如xx模块

的某个查询程序就曾经存在这种情况,见,由于语句的特殊性,在这个脚本中

几个子集的记录绝对不可能重复,故可以改用UNIONALL)

3、对Where语句的法则

3.1避免在WHERE子句中使用in,notin,or或者having。

可以使用exist和notexist代替in和notin。

可以使用表链接代替exist。Having可以用where代替,如果无法代替可

以分两步处理。

例子

SELECT*FROMORDERSWHERECUSTOMERNAMENOTIN

(SELECTCUSTOMER_NAMEFROMCUSTOMER)

优化

SELECT*FROMORDERSWHERECUSTOMER_NAMEnotexist

(SELECTCUSTOMER_NAMEFROMCUSTOMER)

3.2不要以字符格式声明数字,要以数字格式声明字符值。(日期同样)否

则会使索引无效,产生全表扫描。

例子使用:

SELECTemp.ename,emp.jobFROMempWHEREemp.empno=7369;

不要使用:SELECTemp.ename,emp.jobFROMempWHERE

emp.empno=,7369)

4、对Select语句的法则

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

例子

使用SELECTempno,ename,categoryFROMempWHEREempno=,73691

而不要使用SELECT*FROMempWHEREempno=,7369)

5、排序

避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER

BY的SQL语句会启动SQL引擎执行,耗费资源的排序(SORT)功能.DISTINCT需

要一次排序操作,而其他的至少需要执行两次排序。

优化SQLServer数据库方法:

查询速度慢的原因很多,常见如下几种:

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

缺陷)

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

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

4、内存不足

5、网络速度慢

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

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

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

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

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

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

1、把数据、日志、索引放到不同的I/O设备上,增加读取速度,以前可以

将Tempdb应放在RAID0上,SQL2000不在支持。数据量(尺寸)越大,提高I/O

越重要.

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

3、升级硬件

4、根据查询条件,建立索引,优化索引、优化访问方式,限制结果集的数据

量。注意填充因子要适当(最好是使用默认值0)。索引应该尽量小,使用字节

数小的列建索引好(参照索引的创建),不要对有限的几个值的字段建单一索引如

性别字段。

5、提高网速;

6、扩大服务器的内存,Windows2000和SQLserver2000能支持4-8G的

内存。配置虚拟内存:虚拟内存大小应基于计算机上并发运行的服务进行配置。

运行MicrosoftSQLServer2000时,可考虑将虚拟内存大小设置为计算机中安

装的物理内存的L5倍。如果另外安装了全文检索功能,并打算运行

Microsoft搜索服务以便执行全文索引和查询,可考虑:将虚拟内存大小配置

为至少是计算机中安装的物理内存的3倍。将SQLServermaxservermemory

服务器配置选项配置为物理内存的1.5倍(虚拟内存大小设置的一半)。

7、增加服务器CPU个数;但是必须明白并行处理串行处理更需要资源例如

内存。使用并行还是串行程是MsSQL自动评估选择的。单个任务分解成多个任

务,就可以在处理器上运行。例如耽搁查询的排序、连接、扫描和GROUPBY字

句同时执行,SQLSERVER根据系统的负载情况决定最优的并行等级,复杂的需

要消耗大量的CPU的查询最适合并行处理。但是更新操作Update,Insert,

Delete还不能并行处理。

8、如果是使用like进行查询的话,简单的使用index是不行的,但是全

文索引,耗空间。like'a对使用索引like'%a'不使用索引用like'查询时,

查询耗时和字段值总长度成正比,所以不能用CHAR类型,而是VARCHAR。对于

字段的值很长的建全文索引。

9、DBServer和APPLicationServer分离;OLTP和OLAP分离

10、分布式分区视图可用于实现数据库服务器联合体。联合体是一组分开

管理的服务器,但它们相互协作分担系统的处理负荷。这种通过分区数据形成

数据库服务器联合体的机制能够扩大一组服务器,以支持大型的多层Web站点

的处理需要。有关更多信息,参见设计联合数据库服务器。(参照SQL帮助文件

'分区视图')

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

b、在创建成员表后,在每个成员服务器上定义一个分布式分区视图,并且

每个视图具有相同的名称。这样,引用分布式分区视图名的查询可以在任何一

个成员服务器上运行。系统操作如同每个成员服务器上都有一个原始表的复本

一样,但其实每个服务器上只有一个成员表和一个分布式分区视图。数据的位

置对应用程序是透明的。

1k重建索引DBCCREINDEX,DBCCINDEXDEFRAG,收缩数据和日志DBCC

SHRINKDB,DBCCSHRINKFILE.设置自动收缩日志.对于大的数据库不要设置数据

库自动增长,它会降低服务器的性能。在T-sql的写法上有很大的讲究,下面

列出常见的要点:首先,DBMS处理查询计划的过程是这样的:

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

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

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

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

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

6、最后将执行结果返回给用户其次,看一下SQLSERVER的数据存放的结

构:一个页面的大小为8K(8060)字节,8个页面为一个盘区,按照B树存放。

12、Commit和rollback的区别Rollback:回滚所有的事物。Commit:提

交当前的事物.没有必要在动态SQL里写事物,如果要写请写在外面如:begin

tranexec(@s)committrans或者将动态SQL写成函数或者存储过程。

13、在查询Select语句中用Where字句限制返回的行数,避免表扫描,如果

返回不必要的数据,浪费了服务器的I/O资源,加重了网络的负担降低性能。

如果表很大,在表扫描的期间将表锁住,禁止其他的联接访问表,后果严重。

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

15、尽可能不使用光标,它占用大量的资源。如果需要row-by-row地执行,

尽量采用非光标技术,如:在客户端循环,用临时表,Table变量,用子查询,

用Case语句等等。游标可以按照它所支持的提取选项进行分类:只进必须按照

从第一行到最后一行的顺序提取行。FETCHNEXT是唯一允许的提取操作,也是

默认方式。可滚动性可以在游标中任何地方随机提取任意行。游标的技术在

SQL2000下变得功能很强大,他的目的是支持循环。有四个并发选项READONLY:

不允许通过游标定位更新(Update),且在组成结果集的行中没有锁。

OPTIMISTICWITHvalueS:乐观并发控制是事务控制理论的一个标准部分。乐

观并发控制用于这样的情形,即在打开游标及更新行的间隔中,只有很小的机

会让第二个用户更新某一行。当某个游标以此选项打开时,没有锁控制其中的

行,这将有助于最大化其处理能力。如果用户试图修改某一行,则此行的当前

值会与最后一次提取此行时获取的值进行比较。如果任何值发生改变,则服务

器就会知道其他人已更新了此行,并会返回一个错误。如果值是一样的,服务

器就执行修改。选择这个并发选项支PTIMISTICWITHROWVERSIONING:此乐

观并发控制选项基于行版本控制。使用行版本控制,其中的表必须具有某种版

本标识符,服务器可用它来确定该行在读入游标后是否有所更改。在SQL

Server中,这个性能由timestamp数据类型提供,它是一个二进制数字,表示

数据库中更改的相对顺序。每个数据库都有一个全局当前时间戳值:@DBTSo每

次以任何方式更改带有timestamp列的行时,SQLServer先在时间戳列中存储

当前的@DBTS值,然后增加@口8丁5的值。如果某个表具有timestamp列,则时间

戳会被记到行级。服务器就可以比较某行的当前时间戳值和上次提取时所存储

的时间戳值,从而确定该行是否已更新。服务器不必比较所有列的值,只需比

较timestamp列即可。如果应用程序对没有timestamp列的表要求基于行版本

控制的乐观并发,则游标默认为基于数值的乐观并发控制。SCROLLLOCKS这个

选项实现悲观并发控制。在悲观并发控制中,在把数据库的行读入游标结果集

时,应用程序将试图锁定数据库行。在使用服务器游标时,将行读入游标时会

在其上放置一个更新锁。如果在事务内打开游标,则该事务更新锁将一直保持

到事务被提交或回滚;当提取下一行时,将除去游标锁。如果在事务外打开游

标,则提取下一行时,锁就被丢弃。因此,每当用户需要完全的悲观并发控制

时,游标都应在事务内打开。更新锁将阻止任何其它任务获取更新锁或排它锁,

从而阻止其它任务更新该行。然而,更新锁并不阻止共享锁,所以它不会阻止

其它任务读取行,除非第二个任务也在要求带更新锁的读取。滚动锁根据在游

标定义的Select语句中指定的锁提示,这些游标并发选项可以生成滚动锁。滚

动锁在提取时在每行上获取,并保持到下次提取或者游标关闭,以先发生者为

准。下次提取时,服务器为新提取中的行获取滚动锁,并释放上次提取中行的

滚动锁。滚动锁独立于事务锁,并可以保持到一个提交或回滚操作之后。如果

提交时关闭游标的选项为关,则COMMIT语句并不关闭任何打开的游标,而且滚

动锁被保留到提交之后,以维护对所提取数据的隔离。所获取滚动锁的类型取

决于游标并发选项和游标Select语句中的锁提示。锁提示只读乐观数值乐观行

版本控制锁定无提示未锁定未锁定未锁定更新NOLOCK未锁定未锁定未锁定未锁

定HOLDLOCK共享共享共享更新UPDLOCK错误更新更新更新TABLOCKX错误未锁

定未锁定更新其它未锁定未锁定未锁定更新*指定NOLOCK提示将使指定了该提

示的表在游标内是只读的。

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

用索引优化器优化索引

17、注意UNion和UNionall的区别。UNIONall好

18、注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询

变慢。重复的记录在查询里是没有问题的

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

20、用sp_configure'querygovernorcostlimit'或者SET

QUERY_GOVERNOR_COST_LIMIT来限制查询消耗的资源。当评估查询消耗的资源

超出限制时,服务器自动取消查询,在查询之前就扼杀掉。SETLOCKTIME设置

锁的时间

21、用selecttop100/10Percent来限制用户返回的行数或者SET

ROWCOUNT来限制操作的行

22、在SQL2000以前,一般不要用如下的字句:"ISNULL",!

"NOT,"NOTEXISTS","NOTIN","NOTLIKE",and"LIKE'%500'”,因为他

们不走索引全是表扫描。也不要在Where字句中的列名加函数,如Convert,

substring等,如果必须用函数的时候,创建计算列再创建索引来替代.还可以

变通写法:WhereSUBSTRING(firstname,1,1)=,m'改为Wherefirstname

like'm%'(索引扫描),一定要将函数和列名分开。并且索引不能建得太多和太

大。NOTIN会多次扫描表,使用EXISTS、NOTEXISTS,IN,LEFTOUTERJOIN

来替代,特别是左连接,而Exists比IN更快,最慢的是NOT操作.如果列的值

含有空,以前它的索引不起作用,现在2000的优化器能够处理了。相同的是

ISNULL,"NeXT","NOTEXISTS","NOTIN”能优化她,而“”等还是不能优化,用

不到索引。

23、使用QueryAnalyzer,查看SQL语句的查询计划和评估分析是否是优

化的SQL。一般的20%的代码占据了80%的资源,我们优化的重点是这些慢的地

方。

24、如果使用了IN或者OR等时发现查询没有走索引,使用显示申明指定

索引:Select*FROMPersonMember(INDEX=IX_Titie)WhereprocessidIN('男',

'女')

25、将需要查询的结果预先计算好放在表中,查询的时候再Select。这在

SQL7.0以前是最重要的手段。例如医院的住院费计算。

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

27、数据库有一个原则是代码离数据越近越好,所以优先选择Default,依

次为Rules,Triggers,Constraint(约束如外健主健CheckUNIQUE,数据类型的

最大长度等等都是约束),Procedure.这样不仅维护工作小,编写程序质量高,

并且执行的速度快。

28、如果要插入大的二进制值到Image歹!],使用存储过程,千万不要用内

嵌Insert来插入(不知JAVA是否)。因为这样应用程序首先将二进制值转换成

字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值.存储过程

就没有这些动作:方法:Createprocedurep_insertasinsertinto

table(Fimage)values(©image),在前台调用这个存储过程传入二进制参数,这

样处理速度明显改善。

29^Between在某些时候比IN速度更快,Between能够更快地根据索引找到

范围。用查询优化器可见到差别。select*fromchineseresumewheretitle

inC男','女')Select*fromchineseresumewherebetween'男'and'女'是一样

的。由于in会在比较多次,所以有时会慢些。

30、在必要是对全局或者局部临时表创建索引,有时能够提高速度,但不

是一定会这样,因为索引也耗费大量的资源。他的创建同是实际表一样。

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

事物时使用它。

32、用0R的字句可以分解成多个查询,并且通过UNION连接多个查询。他

们的速度只同是否使用索引有关,如果查询需要用到联合索引,用UNIONall执

行的效率更高.多个0R的字句没有用到索引,改写成UNION的形式再试图与索

引匹配。一个关键的问题是否用到索引。

33、尽量少用视图,它的效率低。对视图操作比直接对表操作慢,可以用

storedprocedure来代替她。特别的是不要用视图嵌套,嵌套视图增加了寻找

原始资料的难度。我们看视图的本质:它是存放在服务器上的被优化好了的已

经产生了查询规划的SQLo对单个表检索数据时,不要使用指向多个表的视图,

直接从表检索或者仅仅包含这个表的视图上读,否则增加了不必要的开销,查询

受到干扰.为了加快视图的查询,MsSQL增加了视图索引的功能。

34、没有必要时不要用DISTINCT和ORDERBY,这些动作可以改在客户端

执行。它们增加了额外的开销。这同UNION和UNIONALL一样的道理。

selecttop20

ad.companyname,comid,position,ad.referenceid,worklocation,convert(var

char(10),ad.postDate,120)aspostDatel,workyear,degreedescriptionFROM

jobcn_query.dbo.COMPANYAD_queryadwherereferencelDin('JCNAD

00329667','JCNAD132168'/JCNAD00337748','JCNAD00338345',

'JCNAD00333138'JCNAD00303570),"JCNAD00303569),

"JCNAD00303568'JCNAD00306698',"JCNAD00231935'JCNAD

00231933),

'JCNAD00254567'JCNAD00254585','JCNAD00254608),

'JCNAD00254607'JCNAD00258524'JCNAD00332133'JCNAD

00268618),

"JCNAD00279196','JCNAD00268613')orderbypostdatedesc35、在

IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,

减少判断的次数。

36当用SelectINTO时,它会锁住系统表(sysobjects,sysindexes等

等),阻塞其他的连接的存取。创建临时表时用显示申明语句,而不是select

INTO,droptablet_lxhbegintranselect*intot_lxhfromchineseresume

wherename=,XYZ'-commit在另一个连接中Select*fromsysobjects可以看

到SelectINTO会锁住系统表,Createtable也会锁系统表(不管是临时表还

是系统表)。所以千万不要在事物内使用它!这样的话如果是经常要用的临时表

请使用实表,或者临时表变量。

37、一般在GROUPBY个HAVING字句之前就能剔除多余的行,所以尽量不

要用它们来做剔除行的工作。他们的执行顺序应该如下最优:select的Where

字句选择所有合适的行,GroupBy用来分组个统计行,Having字句用来剔除多

余的分组。这样GroupBy个Having的开销小,查询快.对于大的数据行进行分

组和Having十分消耗资源。如果GroupBY的目的不包括计算,只是分组,那

么用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、SelectCOUNT(*)的效率教低,尽量变通他的写法,而EXISTS快.同时

请注意区别:selectcount(Fieldofnull)fromTable和select

count(FieldofNOTnul1)fromTable的返回值是不同的!

44、当服务器的内存够多时,配制线程数量=最大连接数+5,这样能发挥最

大的效率;否则使用配制线程数量最大连接数启用SQLSERVER的线程池来解决,

如果还是数量=最大连接数+5,严重的损害服务器的性能。

45、按照一定的次序来访问你的表。如果你先锁住表A,再锁住表B,那么

在所有的存储过程中都要按照这个顺序来锁定它们。如果你(不经意的)某个存

储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。如果锁定顺序没

有被预先详细的设计好,死锁很难被发现

46、通过SQLServerPerformanceMonitor监视相应硬件的负载Memory:

PageFaults/sec计数器如果该值偶尔走高,表明当时有线程竞争内存。如果

持续很高,则内存可能是瓶颈。

Process:

1、%DPCTime指在范例间隔期间处理器用在缓延程序调用(DPC)接收和提

供服务的百分比。(DPC正在运行的为比标准间隔优先权低的间隔)。由于DPC

是以特权模式执行的,DPC时间的百分比为特权时间百分比的一部分。这些时

间单独计算并且不属于间隔计算总数的一部分。这个总数显示了作为实例时间

百分比的平均忙时。

2、/ProcessorTime计数器如果该参数值持续超过95%,表明瓶颈是CPU。

可以考虑增加一个处理器或换一个更快的处理器。

3、PrivilegedTime指非闲置处理器时间用于特权模式的百分比。(特权

模式是为操作系统组件和操纵硬件驱动程序而设计的一种处理模式。它允许直

接访问硬件和所有内存。另一种模式为用户模式,它是一种为应用程序、环境

分系统和整数分系统设计的一种有限处理模式。操作系统将应用程序线程转换

成特权模式以访问操作系统服务)。特权时间的强包括为间断和DPC提供服务的

时间。特权时间比率高可能是由于失败设备产生的大数量的间隔而引起的。这

个计数器将平均忙时作为样本时间的一部分显示。

4、%UserTime表示耗费CPU的数据库操作,如排序,执行aggregate

functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水

平分割大表格等方法来降低该值。PhysicalDisk:CurretnDiskQueue

Length计数器该值应不超过磁盘数的L5~2倍。要提高性能,可增加磁盘。

SQLServer:CacheHitRatio计数器该值越高越好。如果持续低于80幅应考

虑增加内存。注意该参数值是从SQLServer启动后,就一直累加记数,所以运

行经过一段时间后,该值将不能反映系统当前值。

47、分析selectemp_nameformemployeewheresalary3000在止匕语句

中若salary是Float类型的,则优化器对其进行优化为Convert(float,3000),

因为3000是个整数,我们应在编程时使用3000.0而不要等运行时让DBMS进行

转化。同样字符和整型数据的转换。

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

selecta.personMemberlD,*fromchineseresumea,personmemberbwhere

personMemberID=b.referenceidand

a.personMemberID='JCNPRH39681'(A=B,B='号码')

selecta.personMemberlD,*fromchineseresumea,personmemberbwhere

a.personMemberID=b.referenceidanda.personMemberID=,JCNPRH39681,and

b.referenceid=,JCNPRH39681'(A=B,B='号码',A='号码')

selecta.personMemberlD,*fromchineseresumea,personmemberbwhere

b.referenceid=,JCNPRH3968Tanda.personMemberID=,JCNPRH39681'(B="号码

',A='号码')

49、

(DIF没有输入负责人代码THENcodel=0code2=9999ELSEcodel=code2=

负责人代码ENDIF执行SQL语句为:Select负责人名FROMP2000Where负责

人代码=:codelAND负责人代码=:code2

(2)IF没有输入负责人代码THENSelect负责人名FROMP2000ELSEcode=

负责人代码Select负责人代码FROMP2000Where负责人代码二:codeENDIF

第一种方法只用了一条SQL语句,第二种方法用了两条SQL语句。在没有输入负

责人代码时,第二种方法显然比第一种方法执行效率高,因为它没有限制条件;

在输入了负责人代码时,第二种方法仍然比第一种方法效率高,不仅是少了一个

限制条件,还因相等运算是最快的查询运算。我们写程序不要怕麻烦

50、关于JOBCN现在查询分页的新方法(如下),用性能优化器分析性能的

瓶颈,如果在I/O或者网络的速度上,如下的方法优化切实有效,如果在CPU

或者内存上,用现在的方法更好。请区分如下的方法,说明索引越小越好。

beginDECLARE@local_variabletable(FIDint

identity(1,1),ReferencelDvarchar(20))

insertinto@local_variable(ReferencelD)

selecttop100000ReferencelDfromchineseresumeorderby

ReferencelDselect*from@local_variablewhereFid40andfid=60end和

beginDECLARE@local_variabletable(FIDint

identity(1,1),ReferencelDvarchar(20))

insertinto@local_variable(ReferencelD)

selecttop100000ReferencelDfromchineseresumeorderby

updatedateseiect*from@local_variablewhereFid40andfid=60end的

不同

begincreatetabletttemp(FIDintidentity(1,1),ReferencelD

varchar(20))

insertinto#temp(ReferencelD)

selecttop100000ReferencelDfromchineseresumeorderby

updatedateselect*from#tempwhereFid40andfid=60droptabletttemp

end

存储过程编写经验和优化措施

一)、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对

SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。

二)、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据

库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写

又没有一定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另

外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优化的问题,

否则速度有可能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的

SP的效率甚至高几百倍。

三)、内容:

1、开发人员如果用到其他库的Table或View,务必在当前库中建立View

来实现跨库操作,最好不要直接使用"databse.dbo.table_name”,因为

sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。

2、开发人员在提交SP前,必须已经使用setshowplan0n分析过查询计

划,做过自身的查询优化检查。

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

a)SQL的使用规范:

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

ii.尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑

先根据条件提取数据到临时表中,然后再做连接。

iii.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过

1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进

行表连接的操作。

iv.注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大

小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围

从大到小。

V.不要在where子句中的〃」左边进行函数、算术运算或其他表达式运算,

否则系统将可能无法正确使用索引。

vi.尽量使用exists代替selectcount(1)来判断是否存在记录,count函

数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。

vii.尽量使用〃=",不要使用

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

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

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

xi.注意insert、update操作的数据量,防止与其他应用冲突。如果数据

量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表

级锁。

b)索引的使用规范:

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

ii.尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通

过indexindex_name来强制指定索引

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

iv.在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到

该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不

会被使用。

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

c)tempdb的使用规范:

i.尽量避免使用distinct、orderby>groupby、having、join、

cumpute,因为这些语句会加重tempdb的负担。

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

iii.在新建临时表时,如果一次性插入数据量很大,那么可以使用select

into代替createtable,避免log,提高速度;如果数据量不大,为了缓和系

统表的资源,建议先createtable,然后insert。

iv.如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建

立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用

到该临时表的索引。

V.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,

先truncatetable,然后droptable,这样可以避免系统表的较长时间锁定。

vi.慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为

这种操作会在一条语句中多次使用tempdb的系统表。

d)合理的算法使用:

根据上面已提到的SQL优化技术和ASETuning手册中的SQL优化内容,结

合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。

具体可用ASE调优命令:setstatisticsioon,setstatisticstimeon,set

showplanon等。

51、SETSHOWPLAN_ALLON查看执行方案。DBCC检查数据库数据完整性。

DBCC(DataBaseConsistencyChecker)是一组用于验证SQLServer数据库完整

性的程序。

52、谨慎使用游标

在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,

再对临时表定义游标进行操作,这样可使性能得到明显提高。

OracleSQL性能优化:

1.选用适合的ORACLE优化器

ORACLE的优化器共有3种

A、RULE(基于规则)b、COST(基于成本)c、CHOOSE(选择性)

设置缺省的优化器,可以通过对init.ora文件中OPTIMIZERJ1ODE参数的

各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS0你当然也在SQL

句级或是会话(session)级对其进行覆盖。

为了使用基于成本的优化器(CBO,Cost-BasedOptimizer),你必须经常运

行analyze命令,以增加数据库中的对象统计信息(objectstatistics)的准确

性。

如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式

将和是否运行过analyze命令有关。如果table已经被analyze过,优化器模

式将自动成为CBO,反之,数据库将采用RULE形式的优化器。

在缺省情况下,ORACLE采用CHOOSE优化器,为了避免那些不必要的全表

扫描(fulltablescan),你必须尽量避免使用CHOOSE优化器,而直接采用基

于规则或者基于成本的优化器。

2.访问Table的方式

ORACLE采用两种访问表中记录的方式:

A、全表扫描

全表扫描就是顺序地访问表中每条记录。ORACLE采用一次读入多个数据块

(databaseblock)的方式优化全表扫描。

B、通过ROWID访问表

你可以采用基于ROWID的访问方式情况,提高访问表的效率,ROWID包含

了表中记录的物理位置信息。ORACLE采用索引(INDEX)实现了数据和存放数据

的物理位置(ROWID)之间的联系。通常索引提供了快速访问ROWID的方法,因此

那些基于索引列的查询就可以得到性能上的提高。

3.共享SQL语句

为了不重复解析相同的SQL语句,在第一次解析之后,ORACLE将SQL语句

存放在内存中。这块位于系统全局区域SGA(systemglobalarea)的共享池

(sharedbufferpool)中的内存可以被所有的数据库用户共享。因此,当你执

行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全

相同,ORACLE就能很快获得已经被解析的语句以及最好的执行路径。ORACLE的

这个功能大大地提高了SQL的执行性能并节省了内存的使用。

可惜的是ORACLE只对简单的表提供高速缓冲(cachebuffering),这个功

能并不适用于多表连接查询。

数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存

区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了。

当你向ORACLE提交一个SQL语句,ORACLE会首先在这块内存中查找相同

的语句。这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共

享,SQL语句必须完全相同(包括空格,换行等)。

数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存

区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了。

共享的语句必须满足三个条件:

A、字符级的比较:当前被执行的语句和共享池中的语句必须完全相同。

B、两个语句所指的对象必须完全相同:

C、两个SQL语句中必须使用相同的名字的绑定变量(bindvariables)o

4.选择最有效率的表名顺序(只在基于规则的优化器中有效)

ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM

子句中写在最后的表(基础表drivingtable)将被最先处理。在FROM子句中包

含多个表的情况下,你必须选择记录条数最少的表作为基础表。当ORACLE处理

多个表时,会运用排序及合并的方式连接它们。首先,扫描第一个表(FROM子

句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第

二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合

并。

如果有3个以上的表连接查询,那就需要选择交叉表(intersectiontable)

作为基础表,交叉表是指那个被其他表所引用的表。

5.WHERE子句中的连接顺序

ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连

接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写

在WHERE子句的末尾。

6.SELECT子句中避免使用’*'

当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用‘*'是

一个方便的方法。不幸的是,这是一个非常低效的方法。实际上,ORACLE在解

析的过程中,会将'*'依次转换成所有的列名,这个工作是通过查询数据字典完

成的,这意味着将耗费更多的时间。

7.减少访问数据库的次数

当执行每条SQL语句时,ORACLE在内部执行了许多工作:解析SQL语句,

估算索引的利用率,绑定变量,读数据块等等。由此可见,减少访问数据库的

次数,就能实际上减少ORACLE的工作量。

8.使用DECODE函数来减少处理时间

使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。

9.整合简单,无关联的数据库访问

如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即

使它们之间没有关系)

10.删除重复记录

11.用TRUNCATE替代DELETE

当删除表中的记录时,在通常情况下,回滚段(rollbacksegments)用来存

放可以被恢复的信息。如果你没有COMMIT事务,ORACLE会将数据恢复到删除

之前的状态(准确地说是恢复到执行删除命令之前的状况)。

而当运用TRUNCATE时,回滚段不再存放任何可被恢复的信息。当命令运行

后,数据不能被恢复。因此很少的资源被调用,执行时间也会很短。

12.尽量多使用COMMIT

只要有可能,在程序中尽量多使用COMMIT,这样程序的性能得到提高,需

求也会因为COMMIT所释放的资源而减少

COMMIT所释放的资源:

A、回滚段上用于恢复数据的信息。

B、被程序语句获得的锁。

C、redologbuffer中的空间。

D、ORACLE为管理上述3种资源中的内部花费。

13.计算记录条数

和一般的观点相反,count(*)比count(1)稍快,当然如果可以通过索引检

索,对索引列的计数仍旧是最快的。例如COUNT(EMPNO)

14,用Where子句替换HAVING子句

避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进

行过滤。这个处理需要排序,总计等操作。如果能通过WHERE子句限制记录的

数目,那就能减少这方面的开销。

15.减少对表的查询

在含有子查询的SQL语句中,要特别注意减少对表的查询。

16.通过内部函数提高SQL效率。

17.使用表的别名(Alias)

当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个

Column±o这样一来,就可以减少解析的时间并减少那些由Column歧义引起

的语法错误。

18,用EXISTS替代IN

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进

行联接。在这种情况下,使用EXISTS(或NOTEXISTS)通常将提高查询的效率。

19.用NOTEXISTS替代NOTIN

在子查询中,NOTIN子句将执行一个内部的排序和合并。无论在哪种情况

下,NOTIN都是最低效的(因为它对子查询中的表执行了一个全表遍历)。为了

避免使用NOTIN,我们可以把它改写成外连接(OuterJoins)或NOTEXISTS0

20.用表连接替换EXISTS

通常来说,采用表连接的方式比EXISTS更有效率。

21.用EXISTS替换DISTINCT

当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在

SELECT子句中使用DISTINCTo一般可以考虑用EXIST替换。

DB2数据库优化

为了帮助DB2DBA避免性能灾难并获得高性能,我为我们的客户、用户和

DB2专家同行总结了一套故障诊断流程。以下详细说明在Unix、Windows和

OS/2环境下使用DB2UDB的电子商务OLTP应用程序的10条最重要的性能改善

技巧-并在本文的结束部分作出总结。

每隔大约几个星期,我们就会接到苦恼的DBA们的电话,抱怨有关性能的

问题。"我们Web站点速度慢得像蜗牛一样“,他们叫苦道,“我们正在失去客户,

情况严重。你能帮忙吗?”为了回答这些问题,我为我的咨询公司开发了一个分

析流程,它能让我们很快找到性能问题的原因,开发出补救措施并提出调整意

见。这些打电话的人极少询问费用和成本-他们只关心制止损失。当DB2或电子

商务应用程序的运行不能达到预期的性能时,组织和财务的收益将遭受极大的

损失。

1.监视开关

确保已经打开监视开关。如果它们没有打开,您将无法获取您需要的性能

信息。要打开该监视开关,请发出以下命令:

db2"updatemonitorswitchesusinglockONsortONbufferpoolON

uowONtableONstatement0N〃

2.代理程序

确保有足够的DB2代理程序来处理工作负载。要找出代理程序的信息,请

发出命令:

db2"getsnapshotfordatabasemanager//

并查找以下行:

Highwatermarkforagentsregistered=7Highwatermarkfor

agentswaitingforatoken=0Agentsregistered=7Agentswaitingfor

atoken=0Idleagents=5Agentsassignedfrompool=158Agentscreated

fromemptyPool=7Agentsstolenfromanotherapplication^Highwater

markforcoordinatingagents=7Maxagentsoverflow=0

如果您发现Agentswaitingforatoken或Agentsstolenfromanother

application不为0,那么请增加对数据库管理器可用的代理程序数(MAXAGENTS

和/或MAX_COORDAGENTS取适用者)。

3.最大打开的文件数

DB2在操作系统资源的约束下尽量做一个“优秀公民”。它的一个〃优秀公民

”的行动就是给在任何时刻打开文件的最大数设置一个上限。数据库配置参数

MAXFIL0P约束DB2能够同时打开的文件最大数量。当打开的文件数达到此数量

时,DB2将开始不断地关闭和打开它的表空间文件(包括裸设备)。不断地打开

和关闭文件减缓了SQL响应时间并耗费了CPU周期。要查明DB2是否正在关闭

文件,请发出以下命令:

db2"getsnapshotfordatabaseonDBNAME”

并查找以下的行:

Databasefilesclosed=0

如果上述参数的值不为0,那么增加MAXFIL0P的值直到不断打开和关闭文

件的状态停填J褂靡韵旅令?/Pdb2"updatedbcfgforDBNAMEusing

MAXFILOPN”

4.锁

LOCKTIMEOUT的缺省值是T

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论