数据库优化
一、优化的错误理解
1.调系统参数
调参数是必要条件,但不是充分条件
2.数据库性能主要是系统问题,是系统管理员工作,与软件开发人员关系不大。
性能问题与所有人相关。
3.数据库性能主要在系统上线,压力增加之后再进行考虑。
开发阶段无需太多考虑。
性能问题与软件工程所有时间周期相关。
4.寄希望于SQL代码的优化,希望能执行得更快点。
性能与语法没有必要的直接关联,不是充分条件。
5.多表连接性能太差,应该通过应用分步骤做。
关系数据库。
6.CPU利用率越低越好
CPU利用率高就认为系统有问题?
举例:10次每次1个串行和1次每次10并行的差异。
7.寄希望于数据处理都在内存完成,不产生磁盘I/O,应该不会再有性能问题?
从内存中获得数据并处理完数据,同样会消耗CPU资源。
二、优化的过程分类
项目的开发过程大致分为3个阶段:设计、开发、部署实施。
注意:设计阶段和开发阶段的优化比例占到80%以上,而上线部署实施之后的优化比例最多20%;
设计阶段优化:
业务规则的优化设计
数据库体系结构的优化设计
数据库逻辑结构设计
数据库物理结构设计
应用系统的设计
开发阶段优化:
合理的索引策略
合理的访问路径
优化SQL语句的分析树
充分使用PL/SQL
减少锁和latch
部署实施阶段的优化
内存和CPU的优化和调整
磁盘I/O和物理结构的设计和调整
系统资源竞争的监测和调整
操作系统平台的优化
二、常用的优化方法
针对交易系统:
预先分配空间(使用uniform而不是auto allocation)
尽量使用BIND变量,提高语句的共享性
CURSOR_SHARING参数设置为SIMILAR/FORCE
不采用或者少采用并行处理技术
普通B*树索引
访问方式主要是按索引进行操作
索引不要太多(4-5个上限)
索引不要太长
定期重建索引
多表连接主要采用嵌套-循环方式(Nested-Loop)
分区技术
物化视图技术
数据仓储系统
索引种类多,除普通B*树索引外,还有Bitmap和Bitmap Join索引
多表连接主要采用HASH连接和排序-匹配方式(Sort-Merge)
定期进行统计信息的采集(频率可降低)
采用并行处理技术
分区技术
物化视图技术
三、优化过程中的要点
A、索引设计和使用在优化过程中的地位;
1)、复合索引的第一字段原则
1.索引第一字段的选择,应为使用频率最高的字段。
2.在使用索引字段作为条件时,如果该索引是联合索引,则必须使用到该索引中的第一个字段
作为条件时才能保证系统使用该索引,否则该索引将不易会被使用,或者索引性能的效果不是最佳。
2)、驱动表的选择
1.驱动表的概念:
表做关联时,要将返回记录少的表作为驱动表,即写在from子句的最后。
注意,是返回记录少的表,不是记录少的表。
2.举例:如表a,b,其中表a返回记录数少,表b返回记录数多:
select a.* from b,a where a.id=b.id
3.原则:大表再前面,小表在后面作为驱动表
4.注意:
a) 多表连接中驱动表的选择:
如果是三个表join同一个字段,如t1.c1 = t2.c1 and t2.c1 =t3.c1,那么交叉表就是t2,因为t2出现了两次,
这个交叉表的选择是个关键,ORACLE会把交叉表作为驱动表,所以我们优化的原则的交叉表尽量的小,在交叉
表中约束条件尽量的多,以使该交叉表返回的记录集尽量的小。
b) 附加限定条件对驱动表的影响
附加条件(除去连接本身),在连接相同的列,附加条件有些时候列上的索引会被限制
比如 where t1.id = t2.id and t2.id =1111.那么附加条件在t2表上,并将其作为驱动表。
如果增加了ordered,那驱动表就是from后的第一个表。
c) 优化器不同对驱动表的选择。
RBO不一定选择最后一个表作为驱动表的, 但会优先选用最后一个表作为驱动表.
例如遇上 要full table scan 的表, RBO会用它作为驱动表.
又例如用到 DBLINK的表, 会先处理 DBLINK的表
3)、索引创建和使用的
1. 索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。
2. 尽可能的使用索引字段作为查询条件,必要时可以通过index index_name来强制指定索引
3. 避免对大表查询时进行table scan,必要时考虑新建索引。
4. 要注意索引的维护,周期性重建索引 ,降低索引树的层级。
B、where子句优化的原则:
规则:
1、如果是多表连接,表连接的条件放在普通条件前
2、如果使用到了索引,该条件靠后
3、根据条件中筛选得到的记录百分比,越小的越靠后
4、数据量大的时候尽量不使用in,根据情况尽可能使用exists
例如:
where a.id=b.id --表连接条件
and a.month='200505' --筛选出记录为总记录的60%
and b.state='B' --筛选出记录为总记录的25%
and a.serv_id='123456' --该字段用到索引
C、临时表的使用原则
1. 尽量避免使用distinct、order by、group by、having、join、因为这些语句会加重临时表的负担。
2. 避免频繁创建和删除临时表,减少系统表资源的消耗。
3. 在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;
如果数据量不大,为了缓和系统表的资源,建议先create table,然后insert。
4. 如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个Oracle存储过程的子存储过程中,
这样才能保证系统能够很好的使用到该临时表的索引。
5. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统
表的较长时间锁定。
6. 慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用temp的系统表。
D、数据分区建议
1. 建议数据进行分区
通常是按日期进行分区,必要条件下可按机构或者区域等进行子分区。
索引尽量使用local分区类型。
2. 建议数据进行散列分布。
减少热点块的发生。
减少数据块的争用。
E、批量并发处理以及对应事务处理原则:
1. 批量数据并发处理。
实现批量数据分类或者按区域进行分区后,并发处理常见方式有:
a) 使用外部批量程序实现数据分类或者分区域处理;
通过编程语言实现多线程或者多子进程子任务实现;
b) 使用存储过程实现数据分类或者分区域处理;
可通过修订存储过程,在存储过程中实现数据分类或者区域区分的参数动态化。
实现调用时多子任务的并发处理。
2. 批量并发程序中的事务处理
在批量程序中,一定要注意事务提交的控制,即处理一定量记录时及时commit。
3. 注意批量数据insert、delete时对执行计划的影响。
备注:该部分和数据表的分区规则设计结合紧密。
F、常被忽视的要点
1. 在Oracle存储过程开发中注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,
尽可能的让字段顺序与索引顺序相一致,范围从大到小。
2. 注意表之间连接的数据类型,避免不同类型数据之间的连接.
3. 注意Oracle存储过程中参数和数据类型的关系。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/759027/viewspace-752677/
,如需转载,请注明出处,否则将追究法律责任。