暂无图片
分享
左磊
2019-03-19
SQL语句优化

SQL语句内容如下:

SELECT to_char(to_date(c.SG2_DEAL_DATE, 'yyyymmdd'), 'yyyy-mm-dd'),

       case

         when length(decrypt_des(a.user_name, get_secrty_key())) = '2' then

          nvl2(decrypt_des(a.user_name, get_secrty_key()),

               substr(decrypt_des(a.user_name, get_secrty_key()), 0, 1) || '*',

               null)

         when length(decrypt_des(a.user_name, get_secrty_key())) = '3' then

          nvl2(decrypt_des(a.user_name, get_secrty_key()),

               substr(decrypt_des(a.user_name, get_secrty_key()), 0, 2) || '*',

               null)

         when length(decrypt_des(a.user_name, get_secrty_key())) >= '4' and

              instr(decrypt_des(a.user_name, get_secrty_key()), '.', 1) > '0' then

          nvl2(decrypt_des(a.user_name, get_secrty_key()),

               substr(decrypt_des(a.user_name, get_secrty_key()),

                      1,

                      instr(decrypt_des(a.user_name, get_secrty_key()), '.', 1) - 1) || '*',

               null)

         else

          nvl2(decrypt_des(a.user_name, get_secrty_key()),

               substr(decrypt_des(a.user_name, get_secrty_key()), 0, 2) || '**',

               null)

       end,

       nvl2(a.CERT_ID,

            substr(decrypt_des(a.CERT_ID, get_secrty_key()), 0, 4) ||

            '**********' ||

            substr(d ecrypt_des(a.CERT_ID, get_secrty_key()), 15, 18),

            null),

       b.card_sub_type,

       c.SG2_CARD_NO,

       c.SG2_DEAL_FEE / 100,

       to_char(to_date(c.SG2_DEAL_DATE || c.SG2_DEAL_TIME,

                       'YYYYMMDDHH24MISS'),

               'yyyy-mm-dd hh:mm:ss') time,

       case

         when c.err_code = '000000' then

          '00'

         else

          '01'

       end,

       c.err_desc,

       c.merchant_no,

       c.workdate

  FROM yy_user_info a, yy_card_info b, qs_wallet_his c

 WHERE c.SG2_DEAL_DATE >= to_char(to_date(:1, 'YYYY-MM-DD'), 'YYYYMMDD')

   AND c.SG2_DEAL_DATE <= to_char(to_date(:2, 'YYYY-MM-DD'), 'YYYYMMDD')

   AND a.user_no(+) = b.user_no

   and b.card_no(+) = c.user_no

在yy_user_info 、yy_card_info 、qs_wallet_his 上的user_no、user_no、SG2_DEAL_DATE 都有索引,只是yy_card_info 该表的user_no有null值,其他表索引字段没有null,但是不知为何不走索引,请大师指点

收藏
分享
6条回答
默认
最新
左磊
上传附件:9d33f5473j153.html
暂无图片 评论
暂无图片 有用 0
打赏 0
章芋文

SQL核心代码:

FROM yy_user_info a, yy_card_info b, qs_wallet_his c
 WHERE c.SG2_DEAL_DATE >= to_char(to_date(:1, 'YYYY-MM-DD'), 'YYYYMMDD')
   AND c.SG2_DEAL_DATE <= to_char(to_date(:2, 'YYYY-MM-DD'), 'YYYYMMDD')
   AND a.user_no(+) = b.user_no
   and b.card_no(+) = c.user_no
复制

执行计划如下:

image.png

唯一的筛选条件就只有一个时间字段,且已经走了索引,另外的两个关联条件是外链接,SQL的优化空间较小,请从业务层面去优化逻辑。

暂无图片 评论
暂无图片 有用 0
打赏 0
lastwinner

从执行计划和SQL写法来看,执行计划本身说不上有无问题

表和索引的结构信息和统计信息、以及数据分布信息拿到后才能进一步分析


你先试试看日期字段条件那里,不用绑定变量,直接写上日期值,执行计划有无变化,效率有无变化。

暂无图片 评论
暂无图片 有用 0
打赏 0
左磊

SQL> select count(*) from YY_USER_INFO;

se

  COUNT(*)

----------

     21112


SQL> lect count(*) from YY_CARD_INFO;

se

  COUNT(*)

----------

    121248


SQL> lect count(*) from QS_WALLET_HIS;


  COUNT(*)

----------

    655112

这些表随着业务增长,数据多会越来越多。表和索引的统计都是最新收集的,指定时间不绑定变量执行计划也是一样不变的

暂无图片 评论
暂无图片 有用 0
打赏 0
lastwinner
如果通过c.SG2_DEAL_DATE的限定返回少量的数据,可考虑nested loop方式,否则hash join是不错的选择。
暂无图片 评论
暂无图片 有用 0
打赏 0
章芋文
问题已关闭: 问题已经得到解决
暂无图片 评论
暂无图片 有用 0
打赏 0
回答交流
Markdown


请输入正文
提交