[转载]数据库优化措施

介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用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 等。
 
 

1.1.1. 简介

临时表是建立在系统临时文件夹中的表,如果使用得当,完全可以像普通表一样进行各种操作,SqlServer的临时表存储在tempdb中,当不再使用时会自动删除。

定义临时表可采用如下两种方式。

第一:声明变量的方式,例如:

DECLARE @T1 table(ProjectNo int,xl_Pipe nvarchar(200));

第二:直接插入的方式,例如:

select tableSum.o_projectno,tableSum.o_projectname,

cast((case when (tableA.Resul is null)then 0.00 else tableA.Resul end)as decimal(18,2))

into #temp1

from

(

    select o_projectno,o_projectname from CDMS_Project

where o_parentno <> 0 and o_type='P'

) as tableSum

我们可以通过以上两种方式构建临时表。但是在采用第二种方式时,对不再使用的临时表需要删除掉,使用drop语句进行删除。例如:

drop table #temp1

1.1.2. 应用场景

临时表主要应用于sql查询语句,使用它能优化性能。在工程项目管理系统中,需要对大量的数据进行汇总、分类、求和等方式的处理,并生成各类报表或图表。采用传统的表连接进行查询,一般一个sql查询语句就会耗时30多秒,因此我们需要对sql查询做性能优化,在此我们可以使用临时表。另外,在以下场景中,我们也可以使用临时表。

(1).   当某一个SQL语句关联的表在2张及以上,并且和一些小表关联。可以采用将大表进行分拆并且得到比较小的结果集合存放在临时表中。

(2).   程序执行过程中可能需要存放一些临时的数据,这些数据在整个程序的会话过程中都需要用的。

1.1.3. 应用示例

在项目的开发过程中,往往会遇到sql语句查询效率过低的问题,这时我们可以采用临时表进行优化。在工程项目管理系统中,大部分的报表及指标数据的查询都使用了临时表,下面以工程范围信息汇总表的SQL语句作为案例,阐述在具体问题上临时表的应用。 关键步骤如下:(完整的sql语句可见工程项目管理系统源代码中的sql语句)

   声明临时表

DECLARE @T2 table(ProjectNo int,xl_Pressure nvarchar(200)); -- 压力

   给临时表赋值     

insert into @T2 (ProjectNo,xl_Pressure)  

select a.ProjectNo,b.xl_Pressure from

(SELECT o_parentno as ProjectNo,o_projectno as TenderID FROM CDMS_Project

where o_type = 'TS') as a

    临时表的应用

select * from

(

SELECT B.ProjectNo,LEFT(UserList,LEN(UserList)-1) as xl_Pressure

FROM

(

   SELECT ProjectNo, (SELECT xl_Pressure+'\' FROM @T2 WHERE ProjectNo=A.ProjectNo FOR XML PATH('')) AS UserList

   FROM @T2 A GROUP BY projectno

 )  B

) as h on h.ProjectNo = A.o_projectno

1.1.4. 取得的成果

通过使用临时表,使sql查询执行时间都从原来的13秒、9秒减少到3秒和5秒,性能得到了提高,而内存消耗有了小幅度的提高,但并不影响系统的性能。使用临时表使SQL语句整体结构性增强,增强SQL语句的可读性。

1.1.5. 存在问题及改进

在应用临时表是应该充分考虑对内存的消耗,以便对系统的性能不会造成影响。


原文地址:https://www.cnblogs.com/fx2008/p/2288358.html