上周给南京某客户一个重要业务系统的数据库做优化,能实施的马上做了实施,优化前后性能对比非常明显,系统最为严重的IO负载过重问题基本得到解决:优化前一天的物理读是48亿次,优化后是15亿次,效果那是刚刚的,业务处理效率明显改善,磁盘的寿命也会有大幅提升。 这些还只是优化建议的一部分。

如果开发人员能把改SQL和业务逻辑的优化建议都完成,一天物理读少于5亿次应该也是完全没问题的。如果不知道优化能够带来如此巨大的提升,可能业务部门会考虑花个上百万换个闪存存储都有可能,实际上当前的普通存储对业务要求来说已经绰绰有余。

当前的性能提升主要是通过调整索引完成的,创建了11个索引。同时还做了调整数据库参数,把optimizer_index_cost_adj参数由20改回默认的100;再有通过hint+sql profile,让sql选择高效执行计划。这些事情DBA可以搞定。但是,如果SQL写的不好,就只能改代码,这个周期可能就比较长了。下面就列举其中的几种情况:

1、部分sql没有使用绑定变量,每秒硬解析次数将近200。这是一个超标很多的数值(硬解析小于10次/秒的系统,基本还算OK)。合理使用绑定变量是OLTP系统的一个最最基本的要求,但是目前还是有很多系统没有使用绑定变量,只能说目前我们国内的很多开发团队的数据库开发水平还很初级。有些公司会要求DBA要有OCP、OCM等资质才能上岗,但是对开发人员却非常宽容,只要功能实现了就算万事大吉,如果经过一些简单的培训,这种不使用绑定变量的低级问题应该不会出现。 这个客户的另一套数据库在某个时段的硬解析接近1000次/秒,CPU使用率接近100%,当DBA告知开发人员这是因为没有使用绑定变量的原因,开发人员居然振振有词的说以前没有出现类似问题,这就是典型的无知者无畏。

不使用绑定变量的一个无奈的解决办法是改数据库参数,将cursor_sharing有默认的exact改成force。这个改动非常不建议,很有可能引起其他性能问题,有很多bug与之相关。

2、这是一个非常低级而且普遍存在的写法问题,对一个日期字段做to_char:where to_char(starttime,'yyyy-mm-dd')='20200110'。这个starttime字段上,已经存在一个单字段索引,还有一个to_char(starttime,'yyyymmdd')函数索引。但是上面的sql写法,如果不改写,就只能再创建一个to_char(starttime,'yyyy-mm-dd')的函数索引。如果开发人员又写出 to_char(starttime,'yyyy/mm/dd')的sql呢?是不是还得再创建一个函数索引?这种sql的存在,说明开发团队还不知道什么是开发规范和SQL审核。

如果你是开发人员,上面两个写法都命中了你(可能有的开发人员仍不知绑定变量写法是个什么概念,建议马上百度一下),那么只能说你的数据库开发水平还有非常巨大的进步空间。

3、select xxseq.nextval from (select 1 from all_objects where rownum<=10) ; 这个sql是借助all_objects视图,生成10个sequence序列值。 这个写法在功能是没问题,但是sql频繁的执行,大量all_objects视图的调用,把这些本来对资源消耗可以忽略不计的sql,变成了top cpu SQL。 建议改成select xxseq.nextval from dual connect by level<=10;

4、select  ...... from xxtab where name like '%这是一个字段内容的完整值%';   SQL(简化版)涉及的表比较大,消耗了大量的IO资源。 随便选择几个两个百分号中间的内容到表里按等值查询,都能查得到,说明两个百分号是可以去掉的,同时like 可以改成=。如果业务上线初期表只有几千或是几万条记录,这个sql消耗的资源也很少,但是随着时间的增长,表的数据量达到千万或上亿,你这样一个SQL就能把大部分IO资源都消耗掉。 凡是使用两个百分号模糊查询为主要过滤条件的,多从业务角度多考虑一下,尽量避免在大表上使用。

5、不明所以,照猫画出狗(不是虎)的分页写法(xxtab这个表很大,sql全表扫描,消耗了大量IO资源):

SELECT * FROM

( SELECT A.*, ROWNUM RN

FROM ( SELECT * FROM xxtab) A

) WHERE RN >= 1

and rownum<= 3000  and ((type = 'typename') and (state = 0));

这个分页写法不知道是从哪里学来的,错的离谱。type和state两个字段上的索引根本用不上,只能使用全表扫描的执行计划。正常的写法应该是:

SELECT A.*, ROWNUM RN

FROM

(SELECT * FROM xxtab

where rownum<= 3000  and ((type = 'typename')  and (state = 0))

) A;   这种写法大表就能用上索引了,IO消耗也会大幅减少。

6、select ... from xxtab where (:b1 is null or col1=:b1) and (:b2 is null or col2=:b2) ;  这种写法,可能来源于某些搜索需求,两个输入框,不管有没有输入查询条件,都可以使用上面的sql。写法简单了,效率却差了很多:不管b1、b2是否有输入,col1和col2字段上即使有索引,也都只能选择全表扫描。 这个在业务上可以要求必须有一个输入条件,那么sql就可以根据不同的输入,生成不同的内容,比如b1有输入,b2无输入:select  .... from xxtab where col1=b1;  两个都有输入,对应sql是select  ... from xxtab where col1=:b1 and col2=:b2; 这样才能高效的使用索引。

7、用rownum分页写法取数:

SELECT *

FROM ( SELECT t.*, ROWNUM RN

FROM ( select t1.*,ROWNUM

from ( select *

from       p

left join  c   on c.objectid = p.objectid

left join  o   on o.objectid = p.objectid

left join  e   on e.objectid = o.objectid

) t1

) t   WHERE ROWNUM < 1500000

) WHERE RN >= 1200000;

这个分页sql的框架完全正确,满分。但是使用场景却是严重不合适的:p表7700万记录(o表也很大),4表left join没有谓词条件,主查询结果集应该也至少是7700万,每次取30万(1500000-1200000)条,要执行250多次,执行计划都是全表扫描,需要两个大表做250多次全表扫描。如果这些sql是串行执行,那么还有一个逻辑问题,就是这些表的数据都是动态变化的,用rownum分页这种方法,一定会造成漏取或重复取数。其实这个sql的最佳做法就是不加分页,一次完成。表扫描只需要一次,而且也不会出现漏取或重复取数的问题。

总结:

SQL优化对大部分系统来说,都能带来非常大的性能提升。很多问题靠更换高级硬件是无法解决的,比如一个大表全表扫描,现有硬件条件执行时间10分钟,更换硬件后执行时间1分钟。而通过优化SQL,建个合适的索引,在不更换硬件的情况下,可能用不到10毫秒就能出结果。

类似的sql写法问题可能还有很多,这次只是挑选了其中一部分top sql做分享。SQL写法灵活多变,性能好的SQL都是符合规范的,性能差的SQL会暴露你的开发水平。

硬解析优化_72最近一次现场生产系统优化的成果与开发建议相关推荐

  1. 硬解析优化_解析!解析!598元的山灵动圈耳机大杀器,横评对比心慌慌

    山灵自千元价位推出超值感三动铁耳机AE3之后,又很快在中端价位放出一款动圈耳机--ME80,目前官方售价598元. 下面谈谈: 包装如上,一如既往的精美和国际化. 看盒子上的图都能发现体积比曾经ME1 ...

  2. mysql 硬解析 软解析_ORACLE sql语句的硬解析与软解析(收藏)

    我们都知道在Oracle中每条SQL语句在执行之前都需要经过解析,这里面又分为软解析和硬解析.那么这两种解析有何不同之处呢?它们又分别是如何进行解析呢?Oracle内部解析的步骤又是如何进行的呢?下面 ...

  3. PLSQL_解析过程及硬解析和软解析的区别(案例)

    2014-08-11 Created By BaoXinjian 一.摘要 Oracle硬解析和软解析是我们经常遇到的问题,所以需要考虑何时产生软解析何时产生硬解析,如何判断 1. SQL的执行过程 ...

  4. 共享SQL语句减少硬解析

    这篇文章是参考甲骨论老相老师所做的教学视频: http://v.youku.com/v_show/id_XMzkyMTczMTQ4.html 所做的学习笔记: 接上文: http://nvd11.bl ...

  5. sql like 绑定变量_码硬解析的改进方法之二使用绑定变量

    绑定变量要求变量名称,数据类型以及长度是一致,否则无法使用软解析 绑定变量(bind variable)是指在DML语句中使用一个占位符,即使用冒号后面紧跟变量名的形式,如下 select * fro ...

  6. SQL解析之硬解析和软解析

    当客户端进程,将SQL语句通过监听器发送到Oracle时, 会触发一个Server process生成,来对该客户进程服务.Server process得到SQL语句之后,对SQL语句进行Hash运算 ...

  7. 资源放送丨《一次特殊的Oralce硬解析性能问题的技术分享》PPT视频

    前段时间,墨天轮邀请云和恩墨SQL优化专家 师庆栋 老师做了<一次特殊的Oralce硬解析性能问题的技术分享>的直播,在这里我们共享一下PPT和视频,供大家参考学习. 日常SQL查询优化常 ...

  8. 今晚直播丨一次特殊的 Oralce 硬解析性能问题的技术分享

    日常SQL查询优化常常遇到的问题是执行时间较长,解决方式通常是针对执行速度进行优化. 此次分享,我将针对具体项目执行中,遇到SQL优化的特殊故障,展开跟大家进行交流.这次SQL优化出现的问题:与执行速 ...

  9. 明晚直播丨一次特殊的 Oralce 硬解析性能问题的技术分享

    日常SQL查询优化常常遇到的问题是执行时间较长,解决方式通常是针对执行速度进行优化. 此次分享,我将针对具体项目执行中,遇到SQL优化的特殊故障,展开跟大家进行交流.这次SQL优化出现的问题:与执行速 ...

最新文章

  1. BUUCTF-Reverse:reverse1
  2. Kafka 对比 ActiveMQ
  3. 剑指offer:63-66记录
  4. Jdk 和 jre 的 关系和区别
  5. 今晚直播 | PostgreSQL基于非易失性内存优化探索
  6. python netsnmp_在Ubuntu18.04中关于Python使用netsnmp进行snmp编程
  7. php操作pdo,PHP PDO操作API
  8. 微软发布Visual Studio Mac预览版
  9. 年前的面试经历(二)
  10. ANSYS网格划分标准及方法
  11. excel文件怎么转成vcf_批量excel转vcf格式的方法
  12. 19行列式公式和代数余子式
  13. iOS 渐变色 以及 镂空效果的实现(Mask的妙用)以及镂空文字的实现
  14. 为什么国内搜索不到国外服务器网站?
  15. js中向数组中添加元素unshift() 方法
  16. EMANet:Expectation-Maximization Attention Networks for Semantic Segmentation论文解读和代码解读
  17. Android中内存泄漏超级精炼详解
  18. AD21下 Gerber文件的理解和导出
  19. 【Java17】全面拥抱Java17,个人企业均恢复免费,开源组织也在跟进,我们还要等待吗?
  20. 企业联合体的形式_企业战略联盟的形式有哪些

热门文章

  1. HighCharts: 设置时间图x轴的宽度
  2. 关于grep,egrep正则表达式的常用用法
  3. Type mismatch: cannot convert from int to Object错误
  4. zookeeper命令行操作
  5. python 编程效率_如何有效提升数据分析效率?五大Python技巧
  6. Java读取HTML传人文件,java读取html文件并获取body中所有的标签及内容的案例.pdf
  7. oracle 经纬度算距离,根据经纬度诀别用java和Oracle存储过程计算两点距离
  8. script filename php,PHP $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 的区别
  9. java的equals方法_Java LocalDateTime类| 带示例的equals()方法
  10. gdb ldexp_带有Python示例的math.ldexp()方法