前阵子遇到一个案例:一个同事说以前一个运行很正常的包,突然间比以前慢了很多,执行时间非常长,晚上的作业调用这个包跑了几个小时也没有跑出数据。于是我在跟踪、优化过程中定位到包中一个存储过程的一段SQL,我将原SQL简化了一下(对应的表名、函数全都随机取名替换掉),大体如下所示,在一个游标中,循环更新表TMP_JO_ORDERS, 其中需要通过函数获取一些值,这些值用来更新目标表的字段值

FOR CUR_JO IN (SELECT JOB_ORDER_NO FROM TMP_JO_ORDERS WHERE SEW_START >=SYSDATE ) LOOP

SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'SEWING','BUTTON')   INTO MY_M_BUTTON FROM DUAL;
        SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'SEWING','LABEL')    INTO MY_M_LABEL  FROM DUAL;
        SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'SEWING','TAPE')     INTO MY_M_TAPE   FROM DUAL;
        SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'SEWING','ZIPPER')   INTO MY_M_ZIPPER FROM DUAL;
        SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'SEWING','OTHERS')   INTO MY_M_OTHERS FROM DUAL;
        SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'THREAD','ALL')      INTO MY_M_THREAD FROM DUAL;
        SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'INTERLINING','ALL') INTO MY_M_INTERLINING FROM DUAL;
        SELECT MAIN_ITC.GET_MUST_INFO(CUR_JO.JOB_ORDER_NO,'PACKING','ALL')     INTO MY_M_PACKING FROM DUAL;
       
        UPDATE TMP_JO_ORDERS A
        SET M_BUTTON=MY_M_BUTTON
             ,M_LABEL=MY_M_LABEL
             ,M_TAPE=MY_M_TAPE
             ,M_ZIPPER=MY_M_ZIPPER
             ,M_OTHERS=MY_M_OTHERS
             ,M_THREAD=MY_M_THREAD
             ,M_INTERLINING=MY_M_INTERLINING
             ,M_PACKING=MY_M_PACKING
        WHERE JOB_ORDER_NO=CUR_JO.JOB_ORDER_NO;
END LOOP;

其实以前运行正常,突然出现性能问题,是因为SELECT JOB_ORDER_NO FROM TMP_JO_ORDERS WHERE SEW_START >=SYSDATE的数据量由于业务量突然增加了很多,所以游标的循环次数从以前几十次突然飚增到8千多次。

假设游标里面的SQL执行时间需要2秒,以前只循环了30次,那么运算该SQL需要2*30=60秒,如果循环次数突然飚增到8000次,2*8000=16000秒,这就是几个小时的时间。你可以想象一下,这个性能会突然下降到一种无法忍受的程度!

那么怎么优化呢? 当然是减少循环次数。仔细观察了这段SQL,弄明白写这个SQL的老兄的业务逻辑后,上面的循环处理完全可以用下面一个SQL语句替换,完全没有必要一条记录一条记录更新。当时修改后测试,发现修改后的SQL,不到1分钟就运行出来了。

UPDATE TMP_JO_ORDERS A
        SET M_BUTTON     =MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'SEWING','BUTTON')
             ,M_LABEL      =MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'SEWING','LABEL')
             ,M_TAPE       =MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'SEWING','TAPE')
             ,M_ZIPPER     =MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'SEWING','ZIPPER')
             ,M_OTHERS     =MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'SEWING','OTHERS')
             ,M_THREAD     =MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'THREAD','ALL')
             ,M_INTERLINING=MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'INTERLINING','ALL')
             ,M_PACKING    =MAIN_INTERFACE.GET_MUST_INFO(JOB_ORDER_NO,'PACKING','ALL')
    WHERE SEW_START >=SYSDATE;

其实这只是一个特殊的案例,我只是将其当做一个引子,引入我想阐述的观点:我们知道SQL是结构化查询语言,擅长于结构化查询,而不擅长于逻辑处理(WHIE、IF..ELSE),但是有时候,很多人喜欢用SQL来处理业务逻辑,当然也不是说不能在存储过程、函数里面做一些业务逻辑处理,只是发现不少人过度放大SQL的逻辑处理功能,将复杂的逻辑运算全部搬到包、存储过程里面处理,例如上面的循环运算,这样做的一个糟糕结果就是性能问题,就好像一个擅长于短跑的人,你硬要他去参加长跑。那么比赛结果肯定不会好到哪里去。

在开发中,我们要对业务逻辑做一些优化处理,避免复杂的逻辑运算,尤其避免循环次数非常大的业务逻辑处理,一方面我们要简化业务逻辑,有些业务逻辑运算转到程序中去处理,另外一方面我们可以用SQL很巧妙的实现很多逻辑复杂的需求,避免我们去做大量复杂的逻辑处理,而不要在复杂的业务下写出更加复杂的SQL语句.例如上面的例子,我以前在一篇文章MS SQL 挑战问题也述说了这样一种观念。

ORACLE应用调优:请避免SQL做大量循环逻辑处理的更多相关文章

  1. OCM_第十四天课程:Section6 —》数据库性能调优_各类索引 /调优工具使用/SQL 优化建议

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  2. 初次使用SQL调优建议工具--SQL Tuning Advisor

    在10g中,Oracle推出了自己的SQL优化辅助工具: SQL优化器(SQL Tuning Advisor :STA),它是新的DBMS_SQLTUNE包. 使用STA一定要保证优化器是CBO模式下 ...

  3. 【原】Learning Spark (Python版) 学习笔记(三)----工作原理、调优与Spark SQL

    周末的任务是更新Learning Spark系列第三篇,以为自己写不完了,但为了改正拖延症,还是得完成给自己定的任务啊 = =.这三章主要讲Spark的运行过程(本地+集群),性能调优以及Spark ...

  4. advisor调优工具优化sql(基于sql_id)

    advisor调优工具优化sql(基于sql_id) 问题背景:客户反馈数据库迁移后cpu负载激增,帮忙查看原因 解决思路:1> 查看问题系统发现有大量的latch: cache buffers ...

  5. Oracle性能调优之物化视图用法简介

    目录 一.物化视图简介 二.实践:创建物化视图 一.物化视图简介 物化视图分类 物化视图分类,物化视图语法和as后面的sql分为: (1) 基于主键的物化视图(主键物化视图) (2)基于Rowid的物 ...

  6. 记一次SQL调优/优化(SQL tuning)——性能大幅提升千倍以上

    好久不写东西了,一直忙于各种杂事儿,恰巧昨天有个用户研发问到我一个SQL调优的问题,说性能太差,希望我能给调优下,最近有些懒,可能和最近太忙有关系,本来打算问问现在的情况,如果差不多就不调了,那哥们儿 ...

  7. Oracle SQL调优系列之SQL Monitor Report

    @ 目录 1.SQL Monitor简介 2.捕捉sql的前提 3.SQL Monitor 参数设置 4.SQL Monitor Report 4.1.SQL_ID获取 4.2.Text文本格式 4. ...

  8. 一个InnoDB性能超过Oracle的调优Case

    年前抽空到兄弟公司支援了一下Oracle迁移MySQL的测试,本想把MySQL调优到接近Oracle的性能即可,但经过 @何_登成 @淘宝丁奇 @淘宝褚霸 @淘伯松 诸位大牛的指导和帮助(排名不分先后 ...

  9. [转]oracle性能调优之--Oracle 10g AWR 配置

    一.ASH和AWR的故事 1.1 关于ASH 我们都知道,用户在ORACLE数据库中执行操作时,必然要创建相应的连接和会话,其中,所有当前的会话信息都保存在动态性能视图V$SESSION中,通过该视图 ...

随机推荐

  1. 【url重写】

    一.原理void Application_BeginRequest(object sender, EventArgs e)    {  //url重写        HttpApplication a ...

  2. ssh整合问题总结--使用HibernateTemplate实现数据分页展示

    在进行大量的数据展示时,必须要使用分页查询,第一次使用在SSH框架整合中使用分页查询,遇到了一些问题,下面以我练习的项目为例详细介绍,如何在Spring+hibernate(+action)的环境下完 ...

  3. (2)从实际项目谈起,基于MEF的插件框架之总体设计

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.MEF框架简介 MEF的全称是Managed Extensibil ...

  4. 读谭浩强C语言数据结构有感(1)

    1.什么是数据结构? 数据结构,就是我们计算机内部的运算,编程语言的基础工作模式吧,个人总结的 = = !! 数据:说简单一点,就是计算机二进制机器码,然后通过一些复杂的操作,变为复杂的语言. 数据元 ...

  5. 基本的window.document操作及实例

    基本的window.document操作及实例 找元素 1.根据id找 var d1 = document.getElementById("d1"); alert(d1); 2.根 ...

  6. [emacs] 使用ggtags浏览代码

    [emacs] 使用ggtags浏览代码 // */ // ]]>   [emacs] 使用ggtags浏览代码 Table of Contents 1 相关的连接 2 global简介 2.1 ...

  7. Hive UDF初探

    1. 引言 在前一篇中,解决了Hive表中复杂数据结构平铺化以导入Kylin的问题,但是平铺之后计算广告日志的曝光PV是翻倍的,因为一个用户对应于多个标签.所以,为了计算曝光PV,我们得另外创建视图. ...

  8. Ionic2学习笔记(10):扫描二维码

    作者:Grey 原文地址: http://www.cnblogs.com/greyzeng/p/5575843.html 时间:6/11/2016     说明: 在本文发表的时候(2016-06-1 ...

  9. cacert.pem

    ## ## Bundle of CA Root Certificates ## ## Certificate data from Mozilla as of: Wed Sep 14 03:12:05 ...

  10. Facebook Paper使用的第三方库

    Facebook Paper使用的第三方库 第三方库名 简介 链接 ACE code editor https://github.com/ajaxorg/ace Appirater 用户评分组件 ht ...