利用分析函数减少对表访问次数

Posted robinson1988

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用分析函数减少对表访问次数相关的知识,希望对你有一定的参考价值。

最近在给一银行客户优化数据仓库,发现了很多烂SQL
下面这条SQL有很好的教学作用,现拿来与大家分享

SQL语句如下:

select /*+ parallel(16) */ count(*)
  from (SELECT HM,
               DZ,
               YB,
               ZZDH,
               ZJLX,
               ZJHM,
               JGBM,
               ZH,
               ZHLX,
               KHRQ,
               YXRQ,
               SFLB,
               FZJG,
               XXLX
          FROM SWP.GRKXHBS_XHX_KH
         WHERE BSH IN
               (SELECT BSH
                  FROM (SELECT 
                         T.BSH, T.DZ, T.YB, T.ZZDH
                          FROM SWP.GRKXHBS_XHX_KH T
                         WHERE T.BSH IN (SELECT T.BSH
                                           FROM SWP.GRKXHBS_XHX_KH T
                                          WHERE NOT EXISTS
                                          (SELECT 
                                                  *
                                                   from swp.grkxhbs_bsh_tmp TMP
                                                  WHERE TMP.INTERNAL_KEY = T.BSH)
                                          GROUP BY T.BSH
                                         HAVING COUNT(*) > 1)
                           AND T.EDATE = '99991231'
                        MINUS
                        SELECT 
                         T.BSH, T.DZ, T.YB, T.ZZDH
                          FROM SWP.GRKXHBS_XHX_KH T
                         WHERE T.BSH IN (SELECT T.BSH
                                           FROM SWP.GRKXHBS_XHX_KH T
                                          WHERE NOT EXISTS
                                          (SELECT 
                                                  *
                                                   from swp.grkxhbs_bsh_tmp TMP
                                                  WHERE TMP.INTERNAL_KEY = T.BSH)
                                          GROUP BY T.BSH
                                         HAVING COUNT(*) > 1)
                           AND EDATE <> '99991231'))
           AND EDATE = '99991231'
           AND DATA_DATE BETWEEN replace('2021-08-23', '-', '') AND
               replace('2021-08-24', '-', '')) tcounttable;

Elapsed: 00:00:08.32

执行计划太乱了,不好格式化,就不贴了

Statistics
----------------------------------------------------------
	924  recursive calls
	  2  db block gets
    1206911  consistent gets
     304135  physical reads
    7214236  redo size
	527  bytes sent via SQL*Net to client
	524  bytes received via SQL*Net from client
	  2  SQL*Net roundtrips to/from client
	 46  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

SQL对GRKXHBS_XHX_KH表访问了5次,可以利用分析函数对上面SQL进行改写,让表只扫描一次,改写之后的SQL如下:

SELECT /*+ parallel(16) */
 COUNT(*)
  FROM (SELECT T.*, MIN(MARK) OVER(PARTITION BY BSH, DZ, YB, ZZDH) EDATE_STATUS
          FROM (SELECT T.*,
                       CASE
                         WHEN EDATE = '99991231' THEN 1
                         WHEN EDATE IS NULL THEN NULL 
                         ELSE
                          0
                       END MARK
                  FROM (SELECT T.*, COUNT(BSH) OVER(PARTITION BY BSH) CNT
                          FROM SWP.GRKXHBS_XHX_KH T
                         WHERE NOT EXISTS    
                         (SELECT *
                                  from swp.grkxhbs_bsh_tmp TMP
                                 WHERE TMP.INTERNAL_KEY = T.BSH)) T
                 WHERE CNT > 1) T
                 ) T 
 WHERE EDATE_STATUS = 1
   and EDATE = '99991231'
   AND DATA_DATE BETWEEN replace('2021-08-23', '-', '') AND
       replace('2021-08-24', '-', '');

Elapsed: 00:00:03.10

Statistics
----------------------------------------------------------
	 96  recursive calls
	  0  db block gets
     294767  consistent gets
	  0  physical reads
	  0  redo size
	527  bytes sent via SQL*Net to client
	524  bytes received via SQL*Net from client
	  2  SQL*Net roundtrips to/from client
	 32  sorts (memory)
	  0  sorts (disk)
	  1  rows processed


SQL改写之后,逻辑读由之前的1206911降低到294767,提升了近5倍性能
这个数据仓库里面有大量的存储过程(6000个)和大量的烂SQL(几千个),要忙死了,脑壳痛

以上是关于利用分析函数减少对表访问次数的主要内容,如果未能解决你的问题,请参考以下文章

利用分析函数减少对表访问次数

利用分析函数减少对表访问次数

面试:聊聊sql优化

分析时间段内对表的操作次数

mysql经典面试题

如何测量代码片段的调用次数和经过时间