随着数据库使用的时间长短,以及现在商业规模的扩大,数据量成级数增长;大数据,云技术等越来越多的海量数据,分析和检索成为数据使用的瓶颈。现在通常是增加硬件投入,增加,增加,增加。无论是工业化还是发电等带给人类的环境污染,还是数据使用的便捷,都值得人类反思。
再多的硬件投入,也无法弥补低效能SQL的过失。
Oracle数据库作为商业数据库的杰出代表。优化程序,减少硬件和电力的消耗才是出路。
优化......
优化......
优化......
提升性能,就是减少CPU,I/O等性能消耗。
一缩小检索范围
①分区表尽量加分区条件;
执行计划区别:(PARTITIONRANGEALL分区全扫)(PARTITIONRANGESINGLE分区范围)
②缩小范围(全扫能否加过滤条件’最好是索引条件’)
③、是否存在没意义的关联条件
如1:A.idin(Selectidfroma1)
①andA.idin(Selectidfroma1whereid=1)
②此时可以注释掉①部分避免没必要的关联和查询。
如2:业务功能类似,功能1需要范围abcde5张表,功能2范围abc3张表;
排除的表/字段都等需求都相同,开发可能为了省事改写,直接将功能2sql直接使用功能1的sql;
最终最外层将不需要字段筛选掉。
④、leftjoin确认能否改成join
leftjoin关联方式存在选错驱动表被驱动表,某些时候可能还会存在量小应该走索引时不走索引。
且产生大量不必要的中间结果,产生大量物理/逻辑读;Join可以过滤数据(过滤条件)。
二查看执行计划cost
cost值小,不一定运行效率好
cost值大,一定运行效率不好
①、小表/小分区变大表/大分区,不统计引起的执行计划错误问题;
②、特殊情况可加hint(driving_site、full、no_index、use_hash..)语句加hint需要和dba协商
数据库统计信息没问题时,大多数没特殊情况都是不需要加hint指定执行计划的;
③、善于用绑定变量;
④、使用标量子查询要量力而行;
⑤、能传入定值部分尽量传入定值
若某字段传一定值,凡是用到这个传定值字段的部分都尽量直接传值(例如:关联条件,groupby等)
oracle在生成执行计划时要通过关联条件等衡量2个表哪个驱动被驱动表,若直接写定值,
数据库会更准确的选择最好的执行计划去数据库中读取数据,groupby排序部分为了减少资源消耗。
执行计划出现如下情况需要严重注意的:
①、CARTESIAN,笛卡尔乘积,需要确认是否有落下的表没有和其他表做关联;
②、filter,驱动表量越大越会引起性能问题;
③、Nestloop驱动表或被驱动表全扫时
最糟糕的情况:驱动表和被驱动表都是全扫,且随着量的增加后续会存在性能问题..
大表做循环--加索引
选择性很差的索引循环--删索引
--2大表做nestloop循环时,需要衡量使用频繁度且尽量和dba协商,来适当加索引;
--nestloop是选择性很差(distinctkey很小)的索引(且执行时间较慢)时,需要dba分析该索引;
若删除索引,建议做个统计确认这几个月是否真的没人用再进行删除;
三一点经验
①、update和merge的选择
如下说的不针对全部情况,具体慢的情况根据业务/数据情况做更改’
update:更改单表,小表关联时比merge速度快,稳定好;
merge:相同表既做更改后字段也做过滤条件时“updateAseti=(selectifrombwherea.id=b.id)wherei(selectifrombwherea.id=b.id)”部分需要额外消耗,可以用merge避免;
②、mergeintowhere条件除更新字段要放到on里
字段:where条件(主键id=1)不走索引,放在on会走主键索引;
子查询:where包含子查询没有放到on里可能存在执行计划没出现子查询关联表的情况,从而导致跑不出结果的情况。
③、不要使用(id=1orin子查询)形式
原因是:执行计划会选择filter,驱动表过滤后条目很多的话,
被驱动表会产生热点块。
④、exists和in的选择(避免filter)
exists比in产生filter执行计划几率大,所以当sql慢,且按F5发现执行计划中有filter可以试着改成in,
若出现in子查询里表全扫或者还存在慢的情况,可以考虑将in(子查询)A与外层B做join关联,
若还存在问题,确认是否存在本文提到的情况,针对整体衡量去优化。
补充:[not]exists子查询里不存在与外层关联的条件,最终结果有无数据的现象
⑤、分页:rownum和row_number的选择
⑥、适当选择使用rowid...
⑦、尽量不写isnull等会引起不走索引的条件,“索引不记录空值”
若字段有nvl函数索引可以写NVL(字段,0))=0来当做isnull判断,可走函数索引
⑧、代码Ifcount0..做判断时,若rownum=1能查出数据就满足count0
就不必全部取出再判断count0...所以这样的判断可以统一加rownum=1
全部做更改后dba需要跟踪sql确认是否有存在rownum缺点引起的问题’
MySQL使用limit1,Oracle使用rownum=1来取数据中一行。
⑨、合理使用临时表解决大量下载功能
⑩、临时用的表:临时属性表?普通表?
临时表:不可统计,create/insert大量后,再调用临时表可能存在选择索引情况引起性能问题可能;
普通表:createasselect...不统计,再调用时,数据库会使用动态采样去产生正确的执行计划;若是insert需要及时统计,否则可能会存在和临时表的问题。
希望有小小的帮助。
预览时标签不可点收录于话题#个上一篇下一篇