High Water Mark导致的SQL效率问题

10.2.0.5.6t1trsn测试库。

 

用户报前台界面操作很慢,30s-120s之间才能完成,通过看日志,找出来是以下sql

select n.id_loan_notice_info as noticeId,

       nvl(n.id_len der_recover, '') as idLenderRecover,

       decode(r.id_lender_recover, null, n.lenderno, b.lenderno) as lenderno,

       decode(r.id_lender_rec over, null, n.lendername, cl.chinese_name) as lendername,

       decode(r.id_lender_recover,

              null,

              n.client_type,

              cl.IS_NATURAL_PERSON) as clientType,

       n.main_contractno as mainContractNo,

       n.contractno as contractNo,

       decode(r.id_lender_recover,

              null,

              nvl(n.contract_ sum, 0),

              nvl(c.contract_sum, 0)) as contractSum,

       decode(r.id_lender_recover, null, n.date_start_recover, r.date_start) as dateStartRecover,

       decode(r.id_lender_recover, null, n.date_end_recover, r.date_end) as dateEndRecover,

       decode(r.id_lender_recover, null, n.date_recover, r.date_recover) as dateRecover,

       decode(r.id_lender_recover, null, n.cmbno, b.cmbno) as cmbno,

       decode(r.id_lender_recover, null, n.cmbname, vc.CMB_NAME) as cmbname,

       n.notice_type as noticeType,

       n.notice_state as noticeState,

       nvl(n.notice_no,

           n.ma in_contractno || '-' || to_char(sysdate, 'yyyyMMdd') || '-' ||

           decode(n.notice_type, '1', 'LX', '2', 'BJ', '3', 'FX', '')) as noticeNo

  from tlms_loa n_notice_info n

  left join tlms_lender_recover r

    on n.id_lender_recover = r.id_lender_recover

 inner join tlms_lender_business_info b

    on n.co ntractno = b.contractno

   and b.data_state = '2'

   and b.delete_flag = 'N'

 inner join tlms_contract_info c

    on b.main_contractno = c.contractno

   and c.dat a_state = '2'

   and c.delete_flag = 'N'

  left join client_info_vw cl

    on b.lenderno = cl.client_no

  left join TCMS_TO_TLMS_TRUST_ACCOUNT_VW v

    on n.cmb no = v.cmb_no

  left join PMS_TO_TLMS_COMBINATION_VW vc

    on b.cmbno = vc.cmbno

 WHERE (select count(1)

          from tlms_lender_recover r

         where r.id_len der_recover = n.id_lender_recover) > 0

   and n.notice_type = ?

   and v.account_type = '01'

   and r.date_en d >= trunc(?)

   and r.date_end <= trunc(?)

 

绑定变量后:

select n.id_loan_notice_info as noticeId,

       nvl(n.id_lender_recover, '') as idLenderRecover,

       decode(r.id_lender_recover, null, n.lenderno, b.lenderno) as lenderno,

       decode(r.id_lender_recover, null, n.lendername, cl.chinese_name) as lendername,

       decode(r.id_lender_recover,

              null,

              n.client_type,

              cl.IS_NATURAL_PERSON) as clientType,

       n.main_contractno as mainContractNo,

       n.contractno as contractNo,

       decode(r.id_lender_recover,

              null,

              nvl(n.contract_sum, 0),

              nvl(c.contract_sum, 0)) as contractSum,

       decode(r.id_lender_recover, null, n.date_start_recover, r.date_start) as dateStartRecover,

       decode(r.id_lender_recover, null, n.date_end_recover, r.date_end) as dateEndRecover,

       decode(r.id_lender_recover, null, n.date_recover, r.date_recover) as dateRecover,

       decode(r.id_lender_recover, null, n.cmbno, b.cmbno) as cmbno,

       decode(r.id_lender_recover, null, n.cmbname, vc.CMB_NAME) as cmbname,

       n.notice_type as noticeType,

       n.notice_state as noticeState,

       nvl(n.notice_no,

           n.main_contractno || '-' || to_char(sysdate, 'yyyyMMdd') || '-' ||

           decode(n.notice_type, '1', 'LX', '2', 'BJ', '3', 'FX', '')) as noticeNo

  from tlms_loan_notice_info n

  left join tlms_lender_recover r

    on n.id_lender_recover = r.id_lender_recover

 inner join tlms_lender_business_info b

    on n.contractno = b.contractno

   and b.data_state = '2'

   and b.delete_flag = 'N'

 inner join tlms_contract_info c

    on b.main_contractno = c.contractno

   and c.data_state = '2'

   and c.delete_flag = 'N'

  left join client_info_vw cl

    on b.lenderno = cl.client_no

  left join TCMS_TO_TLMS_TRUST_ACCOUNT_VW v

    on n.cmbno = v.cmb_no

  left join PMS_TO_TLMS_COMBINATION_VW vc

    on b.cmbno = vc.cmbno

 WHERE (select count(1)

          from tlms_lender_recover r

         where r.id_lender_recover = n.id_lender_recover) > 0

   and n.notice_type = 3

   and v.account_type = '01'

   and r.date_end >= date '2014-03-01'

   and r.date_end < = date '2014-03-31'

 

 

其中涉及的一个表,开发测试都认为有问题,因为如下一个语句,也得执行很久,而表只有800多条。

select * from TLMSDATA.TLMS_LOAN_NOTICE_INFO;

 

统计信息也是显示只有827条,最近一次收集是4天前,38日。

SQL> @stattab TLMS_LOAN_NOTICE_INFO

--@stattab tabname

 

OWNER    TABLE_NAME                       NUM_ROWS LAST_ANALYZED

-------- ------------------------------ ---------- --------------------------------------------------

TLMSDATA TLMS_LOAN_NOTICE_INFO                 827 2014/3/8 0:01:57

 

看统计信息收集历史。

select * from dba_tab_stats_history where owner='TLMSDATA' and table_name='TLMS_LOAN_NOTICE_INFO' order by stats_update_time desc;


 

这个库按照我们的收集策略,是收集启用的。

SQL> @stats_enable

 

GATHER_VALID

---------------

 

STATS_ENABLE

---------------

收集启用

 

--这个表有4.9Ghigh water mark很高,曾经有过大量数据。

SQL> @sizebytab tlmsdata TLMS_LOAN_NOTICE_INFO

   SIZE_MB

----------

      4961

 

--high water mark降下来。

SQL> alter table tlmsdata.TLMS_LOAN_NOTICE_INFO enable row movement;

 

Table altered

 

SQL> alter table tlmsdata.TLMS_LOAN_NOTICE_INFO SHRINK SPACE cascade;

 

Table altered

 

--此时这个表段只占用1M了。

SQL> @sizebytab tlmsdata TLMS_LOAN_NOTICE_INFO

--正确用法 @tabsize owner tab

 

   SIZE_MB

----------

         1

然后用户就反映后台查还是app界面查,都变得很快了。

这个SQL的执行计划,出问题的地方就是如下红框,索引必然也被撑得很大,而shrink cascade会把索引也shrink。


SQL优化到此完毕。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的C++代码展示,用于计算和编码webgl-loader的高水位标记: ```cpp // 计算高水位标记 size_t calculateHighWaterMark(size_t bufferSize, size_t receivedBytes) { // 接收缓冲区的大小 const size_t bufferLength = bufferSize; // 已经接收到的数据字节数 const size_t bytesReceived = receivedBytes; // 计算高水位标记 size_t highWaterMark = bufferLength / 2; if (bytesReceived > highWaterMark) { highWaterMark += bufferLength / 2; } return highWaterMark; } // 编码高水位标记 void encodeHighWaterMark(size_t highWaterMark, std::vector<uint8_t>& data) { // 将高水位标记转换为二进制数据 uint8_t highWaterMarkBytes[sizeof(size_t)]; memcpy(highWaterMarkBytes, &highWaterMark, sizeof(size_t)); // 将二进制数据压缩并加入到数据队列中 std::vector<uint8_t> compressedData = compress(highWaterMarkBytes, sizeof(size_t)); data.insert(data.end(), compressedData.begin(), compressedData.end()); } ``` 在上面的代码中,`calculateHighWaterMark`函数用于计算高水位标记,它接受两个参数:接收缓冲区的大小和已经接收到的数据字节数。该函数首先将高水位标记设置为接收缓冲区大小的一半,然后根据已经接收到的数据字节数来调整高水位标记的大小。如果已经接收到的数据字节数超过了高水位标记的一半,则将高水位标记再增加接收缓冲区大小的一半。 `encodeHighWaterMark`函数用于将高水位标记编码成二进制数据,并将其压缩后加入到数据队列中。该函数接受两个参数:高水位标记和数据队列。该函数首先将高水位标记转换为二进制数据,并使用压缩算法对其进行压缩。最后,将压缩后的数据加入到数据队列中。 需要注意的是,在实际应用中,还需要对高水位标记的解码和处理进行相应的实现,以确保数据的传输和处理的正确性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值