1、数据库访问优化的五个法则程序员
在实际开发,咱们主要是须要对SQL语句进行优化,咱们须要快速定位能性的瓶颈点,也就是说快速找到咱们SQL主要的开销在哪里?根据木桶原理能够知道,最慢的设备每每是性能瓶颈。例如:互联网运用中的带宽,本地数据复制时的硬盘的访问速度。
算法
根据当前计算机硬件的基本性能指标及其在数据库中主要操做内容,能够整理出以下五条性能基本优化法则:sql
(1)减小数据访问(减小磁盘访问)数据库
(2)返回更少数据(减小网络传输或磁盘访问)浏览器
(3)减小交互次数(减小网络传输)性能优化
(4)减小服务器CPU开销(减小CPU及内存开销)服务器
(5) 利用更多资源(增长资源)网络
因为每一层优化法则都是解决其对应硬件的性能问题,因此带来的性能提高比例也不同。传统数据库系统设计是也是尽量对低速设备提供优化方法,所以针对低速设备问题的可优化手段也更多,优化成本也更低。咱们任何一个SQL的性能优化都应该按这个规则由上到下来诊断问题并提出解决方案,而不该该首先想到的是增长资源解决问题。并发
如下是每一个优化法则层级对应优化效果及成本经验参考:oracle
优化法则 |
性能提高效果 |
优化成本 |
减小数据访问 |
1~1000 |
低 |
返回更少数据 |
1~100 |
低 |
减小交互次数 |
1~20 |
低 |
减小服务器CPU开销 |
1~5 |
低 |
利用更多资源 |
@~10 |
高 |
2、数据库访问优化法则详解
2.一、减小数据访问
(1)正确建立索引
索引有哪些种类?
常见的索引有B-TREE索引、位图索引、全文索引,位图索引通常用于数据仓库应用,全文索引因为使用较少,这里不深刻介绍。B-TREE索引包括不少扩展类型,如组合索引、反向索引、函数索引等等,如下是B-TREE索引的简单介绍:
B-TREE索引也称为平衡树索引(Balance Tree),它是一种按字段排好序的树形目录结构,主要用于提高查询性能和惟一约束支持。B-TREE索引的内容包括根节点、分支节点、叶子节点。
咱们通常在什么字段上建索引?
这是一个很是复杂的话题,须要对业务及数据充分分析后再能得出结果。主键及外键一般都要有索引,其它须要建索引的字段应知足如下条件:
1、字段出如今查询条件中,而且查询条件可使用索引;
2、语句执行频率高,一天会有几千次以上;
3、经过字段条件可筛选的记录集很小,那数据筛选比例是多少才适合?
这个没有固定值,须要根据表数据量来评估,如下是经验公式,可用于快速评估:
小表(记录数小于10000行的表):筛选比例<10%;
大表:(筛选返回记录数)<(表总记录数*单条记录长度)/10000/16
单条记录长度≈字段平均内容长度之和+字段数*2
索引对DML(INSERT,UPDATE,DELETE)附加的开销有多少?
这个没有固定的比例,与每一个表记录的大小及索引字段大小密切相关,如下是一个普通表测试数据,仅供参考:
索引对于Insert性能下降56%
索引对于Update性能下降47%
索引对于Delete性能下降29%
所以对于写IO压力比较大的系统,表的索引须要仔细评估必要性,另外索引也会占用必定的存储空间。
(2)只经过索引访问数据
有些时候,咱们只是访问表中的几个字段,而且字段内容较少,咱们能够为这几个字段单独创建一个组合索引,这样就能够直接只经过访问索引就能获得数据,通常索引占用的磁盘空间比表小不少,因此这种方式能够大大减小磁盘IO开销。
(3)优化SQL执行计划
SQL执行计划是关系型数据库最核心的技术之一,它表示SQL执行时的数据访问算法。因为业务需求愈来愈复杂,表数据量也愈来愈大,程序员愈来愈懒惰,SQL也须要支持很是复杂的业务逻辑,但SQL的性能还须要提升,所以,优秀的关系型数据库除了须要支持复杂的SQL语法及更多函数外,还须要有一套优秀的算法库来提升SQL性能。
2.二、返回更少的数据
减小数据的返回也是优化的重要手段,主要有两种方法 分页 和 只返回须要的字段。
(1)分页
分页总共包括三种分页方式:客户端分页、服务端分页、数据库分页。
客服端分页:将数据从应用服务器所有下载到本地应用程序或浏览器,在应用程序或浏览器内部经过本地代码进行分页处理。
优势:编码简单,减小客户端与应用服务器网络交互次数
缺点:首次交互时间长,占用客户端内存
适应场景:客户端与应用服务器网络延时较大,但要求后续操做流畅,如手机GPRS,超远程访问(跨国)等等。
服务端分页:将数据从数据库服务器所有下载到应用服务器,在应用服务器内部再进行数据筛选。
优势:编码简单,只须要一次SQL交互,总数据与分页数据差很少时性能较好。
缺点:总数据量较多时性能较差。
适应场景:数据库系统不支持分页处理,数据量较小而且可控。
数据库分页:采用数据库SQL分页须要两次SQL完成,一个SQL计算总数量,一个SQL返回分页后的数据。
优势:性能好
缺点:编码复杂,各类数据库语法不一样,须要两次SQL交互。
ps:oracle数据库通常采用rownum来进行分页。经常使用分页方式以下
rownum分页:
select * from ( select a.*,rownum rn from (select * from student a where id=? order by status) a where rownum<=20) where rn>10;
rowid分页语法:
select b.* from ( select * from ( select a.*,rownum rn from (select rowid rid,status from student a where id=? order by status) a where rownum<=20) where rn>10) a, student b where a.rid=b.rowid;
(2)只返回须要的字段
经过去除没必要要的返回字段能够提升性能。
优势:
1、减小数据在网络上传输开销
2、减小服务器数据处理开销
3、减小客户端内存占用
4、字段变动时提早发现问题,减小程序BUG
5、若是访问的全部字段恰好在一个索引里面,则可使用纯索引访问提升性能。
缺点:增长编码工做量
2.三、减小交互的次数
(1) batch 操做
数据库访问框架通常都提供了批量提交的接口,jdbc支持batch的提交处理方法,咱们能够批量插入、更新和删除数据。这样交互次数大大减小。采用batch操做通常不会减小不少数据库服务器的物理IO,可是会大大减小客户端与服务端的交互次数,从而减小了屡次发起的网络延时开销,同时也会下降数据库的CPU开销。
(2)in
不少时候咱们须要按一些ID查询数据库记录,咱们能够采用一个ID一个请求发给数据库,以下所示:
for :var in ids[] do begin select * from mytable where id=:var; end;
咱们也能够作一个小的优化, 以下所示,用ID INLIST的这种方式写SQL:
select * from mytable where id in(:id1,id2,...,idn);
经过这样处理能够大大减小SQL请求的数量,从而提升性能。那若是有10000个ID,那是否是所有放在一条SQL里处理呢?答案确定是否认的。首先大部份数据库都会有SQL长度和IN里个数的限制,如ORACLE的IN里就不容许超过1000个值。
另外当前数据库通常都是采用基于成本的优化规则,当IN数量达到必定值时有可能改变SQL执行计划,从索引访问变成全表访问,这将使性能急剧变化。随着SQL中IN的里面的值个数增长,SQL的执行计划会更复杂,占用的内存将会变大,这将会增长服务器CPU及内存成本。
评估在IN里面一次放多少个值还须要考虑应用服务器本地内存的开销,有并发访问时要计算本地数据使用周期内的并发上限,不然可能会致使内存溢出。
综合考虑,通常IN里面的值个数超过20个之后性能基本没什么太大变化,也特别说明不要超过100,超事后可能会引发执行计划的不稳定性及增长数据库CPU及内存成本.
(3)设置Fetch Size
当咱们采用select从数据库查询数据时,数据默认并非一条一条返回给客户端的,也不是一次所有返回客户端的,而是根据客户端fetch_size参数处理,每次只返回fetch_size条记录,当客户端游标遍历到尾部时再从服务端取数据,直到最后所有传送完成。因此若是咱们要从服务端一次取大量数据时,能够加大fetch_size,这样能够减小结果数据传输的交互次数及服务器数据准备时间,提升性能。
2.四、减小数据库服务器CPU运算
(1) 使用绑定变量
Java中Preparestatement就是为处理绑定变量提供的对像,绑定变量有如下优势:
1、防止SQL注入
2、提升SQL可读性
3、提升SQL解析性能,不使用绑定变动咱们通常称为硬解析,使用绑定变量咱们称为软解析。
(2)合理使用排序
(3)减小比较操做
(4)大量复杂运算在客户端处理
2.五、利用更多的资源
(1)客户端多进程并行访问
多进程并行访问是指在客户端建立多个进程(线程),每一个进程创建一个与数据库的链接,而后同时向数据库提交访问请求。当数据库主机资源有空闲时,咱们能够采用客户端多进程并行访问的方法来提升性能。若是数据库主机已经很忙时,采用多进程并行访问性能不会提升,反而可能会更慢。因此使用这种方式最好与DBA或系统管理员进行沟通后再决定是否采用。
(2)数据库并行处理