暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

<Oracle优化新常态> 第五章 SQL优化大法

IT界数据库架构师的漂泊人生 2017-07-27
284


<Oracle优化新常态>第一章

《Oracle优化新常态》第二章强拆(1)

《Oracle优化新常态》第二章强拆(2)

<Oracle优化新常态>  第三章 三大配置

<Oracle优化新常态>第四章 分库分表

<Oracle优化新常态> 第五章 急诊法

SQL是应用程序发给数据库工作的基本单位!所以优化SQL是优化的重中之重。也是立杆见影,成效快,短平快,易出GDP成绩的。但是SQL优化又是个深奥,高深的技术,要充分理解数据库运行机制,也要了解业务特性,以及PL/SQL开发技术。是业务+开发+原理的三位一体!不是一般运维DBA能胜能的,不是会搭建个数据库,搭建个高可用DATAGUARD,搭建个集群RAC,搭建个数据同步OGG的运维DBA就可以优化的。也不是运维工程师能胜能的,虽然你会索引大法。如今SQL是有开发人员写的,自然他们写得好才叫奇迹,写得很垃圾那叫做正常。开发人员工作业绩就是出GDP,而不是出性能。他们连代码质量都无法保证,都要交给测试人员去完成,而且测试人员的数量都是开发人员的两倍。至于性能我就呵呵了! 你说对开发人员做培训,呵呵! 说深了他们又不懂,说潜了他们傲娇觉得鄙视你!


那我就说简单易用易懂而且见效快的SQL优化大法!



第一 优化大法 美图秀秀法


只要是个女人拍照照,必然要美化下自己,PS下自己,何况是个男人啊。所以作为男人写的SQL,也是要爱护自己的面子的,如今大男人主义盛行的年代,虽然IT男字写不好,可代码敲得也要漂亮的喊不要 不要啊!


其一  一段赏心悦目的SQL代码,会给人一种心情愉悦之感。 

其二  可以很快判断出语法问题

其三  可以很快地了解到SQL性能问题所在

其四  见过丑的你才知道什么是美好的


SELECT GW.GW_NO, GW.GW_MER_NO, GW.GW_STATUS, (SELECT COUNT(1) FROM CCPS_TRADERECORD C WHERE C.TR_STATUS = 1 AND C.TR_DATETIME >= TO_DATE(:1, 'yyyy-mm-dd') AND C.TR_DATETIME <TO_DATE(:2, 'yyyy-mm-dd') AND GW.GW_NO = C.TR_GW_NO AND gw.gw_mer_no = c.tr_mer_no AND C.TR_CARDTYPE = :3 ) AS LAST_COUNT, (SELECT COUNT(1) FROM CCPS_TRADERECORD D WHERE D.TR_STATUS = 1 AND D.TR_DATETIME >= TO_DATE(:4, 'yyyy-mm-dd') AND D.TR_DATETIME < TO_DATE(:5, 'yyyy-mm-dd') AND GW.GW_NO = D.TR_GW_NO AND gw.gw_mer_no =

d.tr_mer_no AND D.TR_CARDTYPE = :6 ) TOTAL_CNT, (SELECT COUNT(DISTINCT UN.UP_TR_NO) FROM CCPS_UNNORMAL_PROCESS UN INNER JOIN CCPS_TRADERECORD UT ON UT.TR_NO = UN.UP_TR_NO WHERE UN.UP_CPD_TIME >= TO_DATE(:7, 'yyyy-mm-dd') AND UN.UP_CPD_TIME < TO_DATE(:8, 'yyyy-mm-dd') AND UN.UP_TYPE IN (2, 6) AND UT.TR_CARDTYPE = :9 AND GW.GW_NO = UT.TR_GW_NO AND GW.GW_MER_NO = UT.Tr_Mer_No ) PROTEST_CNT FROM CCPS_GATEWAY GW WHERE GW.GW_STATUS IN (-1, 1)


用PL/SQL格式化工具后这样

SELECT GW.GW_NO,

       GW.GW_MER_NO,

       GW.GW_STATUS,

       (SELECT COUNT(1)

          FROM CCPS_TRADERECORD C

         WHERE C.TR_STATUS = 1

           AND C.TR_DATETIME >= TO_DATE(:1, 'yyyy-mm-dd')

           AND C.TR_DATETIME < TO_DATE(:2, 'yyyy-mm-dd')

           AND GW.GW_NO = C.TR_GW_NO

           AND gw.gw_mer_no = c.tr_mer_no

           AND C.TR_CARDTYPE = :3) AS LAST_COUNT,

       (SELECT COUNT(1)

          FROM CCPS_TRADERECORD D

         WHERE D.TR_STATUS = 1

           AND D.TR_DATETIME >= TO_DATE(:4, 'yyyy-mm-dd')

           AND D.TR_DATETIME < TO_DATE(:5, 'yyyy-mm-dd')

           AND GW.GW_NO = D.TR_GW_NO

           AND gw.gw_mer_no = d.tr_mer_no

           AND D.TR_CARDTYPE = :6) TOTAL_CNT,

       (SELECT COUNT(DISTINCT UN.UP_TR_NO)

          FROM CCPS_UNNORMAL_PROCESS UN

         INNER JOIN CCPS_TRADERECORD UT

            ON UT.TR_NO = UN.UP_TR_NO

         WHERE UN.UP_CPD_TIME >= TO_DATE(:7, 'yyyy-mm-dd')

           AND UN.UP_CPD_TIME < TO_DATE(:8, 'yyyy-mm-dd')

           AND UN.UP_TYPE IN (2, 6)

           AND UT.TR_CARDTYPE = :9

           AND GW.GW_NO = UT.TR_GW_NO

           AND GW.GW_MER_NO = UT.Tr_Mer_No) PROTEST_CNT

  FROM CCPS_GATEWAY GW

 WHERE GW.GW_STATUS IN (-1, 1)


当还是不漂亮,只是不丑了而已,人工化妆下。

SELECT GW.GW_NO,

       GW.GW_MER_NO,

       GW.GW_STATUS,

       (

        SELECT COUNT(1)

          FROM CCPS_TRADERECORD C

         WHERE C.TR_STATUS = 1

           AND C.TR_DATETIME >= TO_DATE(:1, 'yyyy-mm-dd')

           AND C.TR_DATETIME < TO_DATE(:2, 'yyyy-mm-dd')

           AND GW.GW_NO = C.TR_GW_NO

           AND gw.gw_mer_no = c.tr_mer_no

           AND C.TR_CARDTYPE = :3

        ) AS LAST_COUNT,

       (

        SELECT COUNT(1)

          FROM CCPS_TRADERECORD D

         WHERE D.TR_STATUS = 1

           AND D.TR_DATETIME >= TO_DATE(:4, 'yyyy-mm-dd')

           AND D.TR_DATETIME < TO_DATE(:5, 'yyyy-mm-dd')

           AND GW.GW_NO = D.TR_GW_NO

           AND gw.gw_mer_no = d.tr_mer_no

           AND D.TR_CARDTYPE = :6

       ) TOTAL_CNT,

       (

       SELECT COUNT(DISTINCT UN.UP_TR_NO)

          FROM CCPS_UNNORMAL_PROCESS UN

         INNER JOIN CCPS_TRADERECORD UT     ON UT.TR_NO = UN.UP_TR_NO

         WHERE UN.UP_CPD_TIME >= TO_DATE(:7, 'yyyy-mm-dd')

           AND UN.UP_CPD_TIME < TO_DATE(:8, 'yyyy-mm-dd')

           AND UN.UP_TYPE IN (2, 6)

           AND UT.TR_CARDTYPE = :9

           AND GW.GW_NO = UT.TR_GW_NO

           AND GW.GW_MER_NO = UT.Tr_Mer_No

         ) PROTEST_CNT

  FROM CCPS_GATEWAY GW

 WHERE GW.GW_STATUS IN (-1, 1);


再来个丑的

select name,

       value,

       unit,

       (case

         when unit = 'bytes' then

          (value 1024 1024 1024)

         else

          NULL

       end) as UNIT_GB

  from V $PGASTAT;


select name,

         value,

         unit,

case when unit = 'bytes' then (value/1024/1024/1024, 3)  else  NULL  end as UNIT_GB

  from V $PGASTAT;


人工美化原则:

1  select 字段 如果存在计算字段的话,或者对字段额外处理,则每个字段占一行

2  SQL 列长度由原来的80列改成120列,毕竟如今都是宽屏时代了

3  子查询的小挂号单独占一行,以显示出这里有个子查询

4  CASE 一般都是处理SELECT字段的,不能分成多行,必须独占一行,拥挤在一起,因为它们是个逻辑整体,拆多行,大脑无法把上下连在一起。

5 小挂号不要乱用,如上 CASE 前面加个小挂号 (case... ) as  小挂号是提高内部的运算优先级的。加不加小挂号都无法改变的优先级,那就不要加,会干扰视觉。

6 关键字都要右对齐

7 SQL语句应该小写,大写无法快速区分单词

8  请使用新的表连接法   inner join  left join 

9  inner join    on   x.id=y.id  on与join 同在一行

10  FROM 后跟的是主表,紧接着是inner join 表,然后是 left join 最后是其他的

11 select 每个字段最好前面有表名前缀

12 尊重习惯把条件字段左边放    and (sysdate - :2 (24 * 60)) >= trd.tr_datetime


select  a.id,a.name,b.sex,b.btherday,c.country,c.address,d.email

from  a

inner  join b on a.id=b.id

   left  join c  on a.id=c.id

 right  join d on a.id=d.id

where 1=1

    and  a.name='shark'



第二优化大法  条件字段不处理法


所谓条件字段不处理法 是说不对WHERE 后面的字段做任何处理。

select trd.tr_no,

       trd.tr_reference,

       trd.tr_status,

       trd.tr_paystarttime,

       trd.tr_datetime,

       trd.tr_bankcurrency,

       trd.tr_bankamout,

       trd.tr_cha_code,

       ch.cha_merno,

       ch.cha_vpc_accesscode,

       ch.cha_secure_secret,

       trd.TR_SF_DATA,

       trd.TR_CARDTYPE

  from ccps_traderecord trd

  left join ccps_channel ch    on trd.tr_cha_code = ch.cha_code

 where trd.TR_MER_NO != :1

   and trd.tr_checked = 0

   and trd.tr_status != -2

   and (sysdate - :2 (24 * 60)) >= trd.tr_datetime

   and upper(trd.tr_bank_code) = :3

   and rownum <= :4

 order by trd.tr_id asc


这语句的绿色部分对字段做了UPDATE处理。任务对字段做处理都无法利用上该字段的索引。


第三优化大法  隐身大法


所谓隐身 是指默认的优先级 比如字符和日期之间的转换

and a.name=12360

name 是字符类型的字段,而输入的是数字,默认情况下会对name做隐身转换。



第四优化大法 吸星大法

 吸星 是指 星号  * 

一般情况下 大家都喜欢 select *  from a   很省事 快捷,开发人员的最爱。至于会导致什么后果? 我就不说了,select *  你真的需要全部字段吗? 或许你说是! 再问你 你需要这个表将来添加的字段吗? 哦  这个就不晓得了 那麻烦你 把你需要的字段一 一 写出来 好不?

星号确实很便利,当不是这样用的,星号必须远离真实表

如下星号远离 真实表

select  *

from

(

  select  f.*,rownum as rn

  from

  (

    select  a.id,a.name,b.sex,b.btherday,c.country,c.address,d.email

    from  a

    inner  join b on a.id=b.id

       left  join c  on a.id=c.id

     right  join d on a.id=d.id

    where 1=1

        and  a.name='shark'

    order by a.name desc

  ) f

 where rn <=10 


第五优化大法 绑定变量法


此法只适应于 OLTP 和OLQP两种请求类型

所谓的绑定变量,也就是开发人员常见的参数,定义个形参,真实运行的时候传递个实参。如下 JAVA一般是问号


    select  a.id,a.name,b.sex,b.btherday,c.country,c.address,d.email

    from  a

    inner  join b on a.id=b.id

       left  join c  on a.id=c.id

     right  join d on a.id=d.id

    where 1=1

        and  a.name=?


为何要如此呢? 那是因为应用程序发给数据库的SQL 都是明文的字符编码,是我们人类看得懂的,机器看不懂的。机器只看得懂二进制的1010010。

因此数据库需要把传来的字符SQL命令翻译成二进制的1010,而这个工作叫做 编译或者是解释。搞过开发人都知道编译和解释都需要耗费CPU时间的。

虽然一个简单的SQL编译一次消耗不了多少CPU时间。如下图

其中4个SELECT 执千次以上,一天时间内24小时中。还好目前这些语句都绑定了变量。



虽然小凡仙我觉得,这五条大法或许很多人看不上眼,或许也解决不了你目前的SQL性能问题。如果你结合强拆,分库分表,三大配置,已经本章的5大法。那么小仙认为你的数据库性能问题,基本上进一步缩小在可控的范围中。


苹果手机用户打赏区




                                                                                有想法请在这里留言-->


祖仙教

祖仙的神话

祖仙教

祖仙教-性


过往文章目录

理科精华

RAC crs_stat 命令结果完整显示

归档日志比在线日志小

分区表

INDEX肥胖化

OracleDG 备库 STANDBY 日志传输小结

ORACLE索引名称矫情

ASM中的几个概念

抓取性能不错的脚本

RMAN duplicate 方式做个备库

DG中归档日志删除遇警告

direct path read

共享池内存三维

PGA内存

一个性能优化案例INSERT

SGA内存

Linux 64 页表,进程内存,大页

Linux_x86_64BIT内存管理与分布

部分SWAP 内存知识

理解队列锁

ORACLE闪回之闪回查询

ORACLE 闪回之闪回删除

ORACLE闪回之闪回表

ORACL 闪回功能之闪回数据库

ORACLE 索引全扫描逻辑读

解析过程中的软软解析

ORACLE索引范围扫描逻辑读ARRAY

UNDO

归档日志比在线日志小

RAC 修改 IP

RAC

ASM 再平衡

RAC安装

使用UDEV绑定ASM盘符

网络命名关系图


RAC 修改私有网卡IP

RAC私网修改错了咋办

只有数据文件情况下恢复数据库

<Oracle优化新常态>第一章

《Oracle优化新常态》第二章强拆(1)

《Oracle优化新常态》第二章强拆(2)

<Oracle优化新常态>第三章 三大配置


文史经典

纸版书和电子书

爱情是什么

IT界程序员泡妞《葵花宝典》

读书日谈读书

反对道德恐怖主义

论当今的婚介公司如何赚钱

失眠三重天

明朝灭亡真想

祖仙曰:万事皆亡

活见鬼

IT界人员提高智商

21世纪孩子的教育

祖仙教

家庭常平仓

北韩的高辐射性核武器

吵架时候男人避免10点可以继续幸福下去

亲戚借钱条款

给英国防YSL极端恐怖支两招

八十岁老人上飞机扔硬币进发动机

剩女招聘老公--爱情婚姻新思维


财经经典

西帝和东帝谈判成果

岁月静好-两场战争

熊案--马后炮

税收制度是穷人在交税养富人

房价再次限购后资金的流向?

加息的马后炮

P2P和换汇的生意

房地产资金流

静待股市台风信息-上

股市的制胜之道

股市事后诸葛亮

藏债与民

股市与理财产品

黄金获利逃顶

黄金如期下跌

楼市第六限--->限婚

M2什么情况下才会减少?

黄金差不多跌够了

黄金又跌了--凡仙分析法

黄金好像到了该买涨的时候了


最后修改时间:2020-10-12 12:18:12
文章转载自IT界数据库架构师的漂泊人生,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论