天天看點

關于latch: cache buffers chains的sql優化

前段時間,優化了一些耗buffer比較多的sql,但是CPU使用率還是沒下來 。

檢視作業系統CPU使用率

關于latch: cache buffers chains的sql優化

檢視awr,發現又有一條超級耗性能的sql冒出來了。

關于latch: cache buffers chains的sql優化
關于latch: cache buffers chains的sql優化
該SQL每次執行耗費3e多個buffer,結果就是導緻記憶體消耗高,cpu消耗也高。。。

利用工具PLSQL Developer,查詢執行該SQL的session

關于latch: cache buffers chains的sql優化
資料庫的等待事件為latch: cache buffers chains

SQL代碼:

select distinct to_char(t5.summaryno) settlementNo,
                to_char(t5.batchtype) settlementType,
                to_char(s.writeouttype) certitype,
                to_char(t5.payconfirmsequenceno) payConfirmSequenceNo,
                to_char(t5.commissionpayno) CommissionPayNo,
                to_char(t2.amount) payAmount,
                to_char(t2.currencycode) payCurrency,
                (case
                  when t5.unitcode = '012100' then
                   (select to_char(d.timestamp, 'YYYY-MM-DD HH24:mi:ss')
                      from mm_dailyreport_detail_td d
                     where d.seqreportno = t1.seqreportno)
                  else
                   to_char(t2.opdate, 'YYYY-MM-DD HH24:mi:ss')
                end) payDate,
                to_char(s.batch_id) batchid,
                t2.coreason payErrorMessage,
                '' payedExchangedRate,
                (select distinct o.voucherno
                   from mm_sap_voucher_detail_to o
                  where o.businessno = t2.inpaymentid
                    and o.dailyauditno = t3.dailyauditno) accountingDocuments,
                (case
                  when t2.amount >  then
                   '02'
                  when t2.amount <  then
                   '03'
                  when t2.amount =  then
                   '01'
                end) payStatus,
                to_char(t2.inpaymentid) ebankSequenceNo
  from mm_writeout_to         t1,
       mm_inpayment_td        t2,
       mm_paymentin_events_td t3,
       mm_payablemoney_td     t4,
       mm_batchinfo_td        t5,
       mm_batchinfo_ti        t6,
       mm_writeoutstatus_to   s
 where t2.inpaymentid = t1.businessno
   and t1.id = s.id
   and t3.newno = t2.inpaymentid
   and ((t3.oldno = t4.payableno) or exists
        (select 
           from mm_paymentin_events_td p
          where p.listno = t3.fatherno
            and t4.payableno = p.oldno))
   and t6.id = t5.seqbatch
   and t6.status = '2'
   and t5.opstatus = '0'
   and t5.serialno = t4.custseq
   and s.batch_id = :
   and exists (select 
          from mm_sap_voucher_detail_to o
         where o.businessno = t2.inpaymentid              
           and o.dailyauditno = t3.dailyauditno)
   and s.status in ('00', 'XX')
           

該sql中有個變量值 s.batch_id = :1,利用系統視圖dba_hist_sqlbind找出綁定變量值,在測試環境測試,發現每次執行都隻要334個buffer

關于latch: cache buffers chains的sql優化
關于latch: cache buffers chains的sql優化

執行計劃沒錯?隻消耗334個buffer,而且1s内出結果,完全不像awr中記錄的。

dba_hist_sqlbind:查詢曆史綁定變量資訊, dba_hist_sqlbind的資訊是從v$sql_bind_capture裡面采集的。

v$sql_bind_capture view:隻儲存最後一次捕獲SQL的變量資訊,兩次捕獲之間的間隔為900s,受隐藏參數控制

再次利用視圖v$sql_bind_capture抓取最新的值,代入sql中執行,發現sql卡住了。。

檢視sql特殊執行計劃

Plan hash value: 

-------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name                          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------------------------
|    |  TABLE ACCESS BY INDEX ROWID           | MM_DAILYREPORT_DETAIL_TD      |       |       |       |:: |        |       |       |          |
|*   |   INDEX UNIQUE SCAN                    | PK_MM_DAILYREPORT_DETAIL_TD   |       |       |       |:: |        |       |       |          |
|    |  HASH UNIQUE                           |                               |       |       |       |:: |        |  K|  K|  K ()|
|    |   TABLE ACCESS BY INDEX ROWID          | MM_SAP_VOUCHER_DETAIL_TO      |       |       |       |:: |        |       |       |          |
|*   |    INDEX RANGE SCAN                    | IDX_MM_SAP_VOUCHER_DETAIL_TO1 |       |       |       |:: |        |       |       |          |
|    |  HASH UNIQUE                           |                               |       |       |       |:: |     M|   K|   K|  K ()|
|*   |   FILTER                               |                               |       |        |     |:: |     M|       |       |          |
|    |    TABLE ACCESS BY INDEX ROWID         | MM_PAYABLEMONEY_TD            |       |       |     M|:: |     M|       |       |          |
|    |     NESTED LOOPS                       |                               |       |       |     M|:: |     M|       |       |          |
|   |      NESTED LOOPS                      |                               |       |       |     M|:: |     M|       |       |          |
|   |       MERGE JOIN CARTESIAN             |                               |       |       |     M|:: |    |       |       |          |
|   |        NESTED LOOPS SEMI               |                               |       |       |     |:: |       |       |       |          |
|   |         NESTED LOOPS                   |                               |       |       |     |:: |       |       |       |          |
|   |          NESTED LOOPS                  |                               |       |       |       |:: |       |       |       |          |
|   |           NESTED LOOPS                 |                               |       |       |       |:: |       |       |       |          |
|   |            INLIST ITERATOR             |                               |       |        |       |:: |        |       |       |          |
|   |             TABLE ACCESS BY INDEX ROWID| MM_WRITEOUTSTATUS_TO          |       |       |       |:: |        |       |       |          |
|*  |              INDEX RANGE SCAN          | IDX_WRITEOUTSTATUS_TEST       |       |       |       |:: |        |       |       |          |
|   |            TABLE ACCESS BY INDEX ROWID | MM_WRITEOUT_TO                |       |       |       |:: |        |       |       |          |
|*  |             INDEX UNIQUE SCAN          | PK_MM_WRITEOUT_TO             |       |       |       |:: |        |       |       |          |
|   |           TABLE ACCESS BY INDEX ROWID  | MM_INPAYMENT_TD               |       |       |       |:: |        |       |       |          |
|*  |            INDEX UNIQUE SCAN           | PK_MM_INPAYMENT_TD            |       |       |       |:: |        |       |       |          |
|   |          TABLE ACCESS BY INDEX ROWID   | MM_PAYMENTIN_EVENTS_TD        |       |       |     |:: |       |       |       |          |
|*  |           INDEX RANGE SCAN             | IDX_PAYMENTINE_07             |       |       |     |:: |        |       |       |          |
|*  |         INDEX RANGE SCAN               | IDX_MM_SAP_VOUCHER_DETAIL_TO1 |       |    |       |:: |        |       |       |          |
|   |        BUFFER SORT                     |                               |     |    K|     M|:: |    |    M|  K|   M ()|
|*  |         TABLE ACCESS FULL              | MM_BATCHINFO_TD               |       |    K|    K|:: |    |       |       |          |
|*  |       TABLE ACCESS BY INDEX ROWID      | MM_BATCHINFO_TI               |     M|       |     M|:: |     M|       |       |          |
|*  |        INDEX UNIQUE SCAN               | PK_BATCHINFO_TI               |     M|       |     M|:: |     M|       |       |          |
|*  |      INDEX RANGE SCAN                  | IDX_PAYABLEMONEY_09           |     M|       |     M|:: |     M|       |       |          |
|*  |    INDEX RANGE SCAN                    | IDX_PAYMENTINE_TEST           |     M|       |       |:: |        |       |       |          |
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

    - access("D"."SEQREPORTNO"=TO_NUMBER(:B1))
    - access("O"."DAILYAUDITNO"=:B1)
       filter(TO_NUMBER("O"."BUSINESSNO")=:B1)
    - filter(("T3"."OLDNO"="T4"."PAYABLENO" OR  IS NOT NULL))
   - access((("S"."STATUS"='' OR "S"."STATUS"='XX')) AND "S"."BATCH_ID"='')
   - access("T1"."ID"="S"."ID")
   - access("T2"."INPAYMENTID"=TO_NUMBER("T1"."BUSINESSNO"))
   - access("T3"."NEWNO"="T2"."INPAYMENTID")
   - access("O"."DAILYAUDITNO"="T3"."DAILYAUDITNO")
       filter("T2"."INPAYMENTID"=TO_NUMBER("O"."BUSINESSNO"))
   - filter("T5"."OPSTATUS"='0')
   - filter("T6"."STATUS"='')
   - access("T6"."ID"="T5"."SEQBATCH")
   - access("T5"."SERIALNO"="T4"."CUSTSEQ")
   - access("P"."LISTNO"=:B1 AND "P"."OLDNO"=:B2)


 rows selected.
           

id=11處 ,a-rows并不是0條,而是有64000000條記錄。他的父級 的連接配接方式是 NEST LOOP,

也就是說被驅動表MM_BATCHINFO_TI表要被掃描64000000次。。。

定位到問題點,現在就開始優化吧。

嘗試優化1:

利用hint(/+ OPT_PARAM(‘_optimizer_mjc_enabled’,’false’) /)禁用笛卡爾積

關于latch: cache buffers chains的sql優化
不見效果,此優化方法失敗。

嘗試優化2:

利用hint 走hash的連接配接方式

關于latch: cache buffers chains的sql優化
不見效果,此優化方法也失敗。

嘗試優化3:

從sql代碼中看出,該SQLwhere條件又or子查詢,嘗試利用union改寫or

select distinct to_char(t5.summaryno) settlementNo,
                to_char(t5.batchtype) settlementType,
                to_char(s.writeouttype) certitype,
                to_char(t5.payconfirmsequenceno) payConfirmSequenceNo,
                to_char(t5.commissionpayno) CommissionPayNo,
                to_char(t2.amount) payAmount,
                to_char(t2.currencycode) payCurrency,
                (case
                  when t5.unitcode = '012100' then
                   (select to_char(d.timestamp, 'YYYY-MM-DD HH24:mi:ss')
                      from mm_dailyreport_detail_td d
                     where d.seqreportno = t1.seqreportno)
                  else
                   to_char(t2.opdate, 'YYYY-MM-DD HH24:mi:ss')
                end) payDate,
                to_char(s.batch_id) batchid,
                t2.coreason payErrorMessage,
                '' payedExchangedRate,
                (select distinct o.voucherno
                   from mm_sap_voucher_detail_to o
                  where o.businessno = t2.inpaymentid
                    and o.dailyauditno = t3.dailyauditno) accountingDocuments,
                (case
                  when t2.amount >  then
                   '02'
                  when t2.amount <  then
                   '03'
                  when t2.amount =  then
                   '01'
                end) payStatus,
                to_char(t2.inpaymentid) ebankSequenceNo
  from mm_writeout_to         t1,
       mm_inpayment_td        t2,
       mm_paymentin_events_td t3,
       mm_payablemoney_td     t4,
       mm_batchinfo_td        t5,
       mm_batchinfo_ti        t6,
       mm_writeoutstatus_to   s
 where t2.inpaymentid = t1.businessno
   and t1.id = s.id
   and t3.newno = t2.inpaymentid
   and t3.oldno = t4.payableno
   and t6.id = t5.seqbatch
   and t6.status = '2'
   and t5.opstatus = '0'
   and t5.serialno = t4.custseq
   and s.batch_id = '1219639828'
   and exists (select 
          from mm_sap_voucher_detail_to o
         where o.businessno = t2.inpaymentid              
           and o.dailyauditno = t3.dailyauditno)
   and s.status in ('00', 'XX')
union
select distinct to_char(t5.summaryno) settlementNo,
                to_char(t5.batchtype) settlementType,
                to_char(s.writeouttype) certitype,
                to_char(t5.payconfirmsequenceno) payConfirmSequenceNo,
                to_char(t5.commissionpayno) CommissionPayNo,
                to_char(t2.amount) payAmount,
                to_char(t2.currencycode) payCurrency,
                (case
                  when t5.unitcode = '012100' then
                   (select to_char(d.timestamp, 'YYYY-MM-DD HH24:mi:ss')
                      from mm_dailyreport_detail_td d
                     where d.seqreportno = t1.seqreportno)
                  else
                   to_char(t2.opdate, 'YYYY-MM-DD HH24:mi:ss')
                end) payDate,
                to_char(s.batch_id) batchid,
                t2.coreason payErrorMessage,
                '' payedExchangedRate,
                (select distinct o.voucherno
                   from mm_sap_voucher_detail_to o
                  where o.businessno = t2.inpaymentid
                    and o.dailyauditno = t3.dailyauditno) accountingDocuments,
                (case
                  when t2.amount >  then
                   '02'
                  when t2.amount <  then
                   '03'
                  when t2.amount =  then
                   '01'
                end) payStatus,
                to_char(t2.inpaymentid) ebankSequenceNo
  from mm_writeout_to         t1,
       mm_inpayment_td        t2,
       mm_paymentin_events_td t3,
       mm_payablemoney_td     t4,
       mm_batchinfo_td        t5,
       mm_batchinfo_ti        t6,
       mm_writeoutstatus_to   s
 where t2.inpaymentid = t1.businessno
   and t1.id = s.id
   and t3.newno = t2.inpaymentid
   and exists
        (select 
           from mm_paymentin_events_td p
          where p.listno = t3.fatherno
            and t4.payableno = p.oldno)
   and t6.id = t5.seqbatch
   and t6.status = '2'
   and t5.opstatus = '0'
   and t5.serialno = t4.custseq
   and s.batch_id = '1219639828'
   and exists (select 
          from mm_sap_voucher_detail_to o
         where o.businessno = t2.inpaymentid              
           and o.dailyauditno = t3.dailyauditno)
   and s.status in ('00', 'XX')

--執行計劃:
Plan hash value: 

-------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name                          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------------------------
|    |  SORT UNIQUE                           |                               |       |       |       |:: |     |   |   |   ()|
|    |   UNION-ALL                            |                               |       |        |     |:: |     |       |       |          |
|    |    NESTED LOOPS SEMI                   |                               |       |       |     |:: |     |       |       |          |
|    |     NESTED LOOPS                       |                               |       |       |     |:: |     |       |       |          |
|    |      NESTED LOOPS                      |                               |       |       |     |:: |      |       |       |          |
|    |       NESTED LOOPS                     |                               |       |       |     |:: |      |       |       |          |
|    |        NESTED LOOPS                    |                               |       |       |     |:: |       |       |       |          |
|    |         NESTED LOOPS                   |                               |       |       |       |:: |       |       |       |          |
|    |          NESTED LOOPS                  |                               |       |       |       |:: |       |       |       |          |
|   |           INLIST ITERATOR              |                               |       |        |       |:: |        |       |       |          |
|   |            TABLE ACCESS BY INDEX ROWID | MM_WRITEOUTSTATUS_TO          |       |       |       |:: |        |       |       |          |
|*  |             INDEX RANGE SCAN           | IDX_WRITEOUTSTATUS_TEST       |       |       |       |:: |        |       |       |          |
|   |           TABLE ACCESS BY INDEX ROWID  | MM_WRITEOUT_TO                |       |       |       |:: |        |       |       |          |
|*  |            INDEX UNIQUE SCAN           | PK_MM_WRITEOUT_TO             |       |       |       |:: |        |       |       |          |
|   |          TABLE ACCESS BY INDEX ROWID   | MM_INPAYMENT_TD               |       |       |       |:: |        |       |       |          |
|*  |           INDEX UNIQUE SCAN            | PK_MM_INPAYMENT_TD            |       |       |       |:: |        |       |       |          |
|   |         TABLE ACCESS BY INDEX ROWID    | MM_PAYMENTIN_EVENTS_TD        |       |      |     |:: |       |       |       |          |
|*  |          INDEX RANGE SCAN              | IDX_PAYMENTINE_08             |       |      |     |:: |        |       |       |          |
|   |        TABLE ACCESS BY INDEX ROWID     | MM_PAYABLEMONEY_TD            |     |       |     |:: |      |       |       |          |
|*  |         INDEX UNIQUE SCAN              | PK_MM_PAYABLEMONEY_TD         |     |       |     |:: |      |       |       |          |
|   |       TABLE ACCESS BY INDEX ROWID      | MM_BATCHINFO_TD               |     |       |     |:: |      |       |       |          |
|*  |        INDEX RANGE SCAN                | IDX_BATCH_TD_SERIALNO         |     |       |     |:: |      |       |       |          |
|*  |      INDEX RANGE SCAN                  | IDX_BATCHINFO_TI_01           |     |       |     |:: |      |       |       |          |
|*  |     INDEX RANGE SCAN                   | IDX_MM_SAP_VOUCHER_DETAIL_TO1 |       |    |       |:: |        |       |       |          |
|   |    NESTED LOOPS SEMI                   |                               |       |       |       |:: |       |       |       |          |
|   |     NESTED LOOPS                       |                               |       |       |       |:: |       |       |       |          |
|   |      NESTED LOOPS                      |                               |       |       |       |:: |       |       |       |          |
|   |       NESTED LOOPS                     |                               |       |       |       |:: |       |       |       |          |
|   |        NESTED LOOPS                    |                               |       |       |       |:: |       |       |       |          |
|   |         NESTED LOOPS                   |                               |       |       |       |:: |       |       |       |          |
|   |          NESTED LOOPS                  |                               |       |       |       |:: |       |       |       |          |
|   |           NESTED LOOPS                 |                               |       |       |       |:: |       |       |       |          |
|   |            INLIST ITERATOR             |                               |       |        |       |:: |        |       |       |          |
|   |             TABLE ACCESS BY INDEX ROWID| MM_WRITEOUTSTATUS_TO          |       |       |       |:: |        |       |       |          |
|*  |              INDEX RANGE SCAN          | IDX_WRITEOUTSTATUS_TEST       |       |       |       |:: |        |       |       |          |
|   |            TABLE ACCESS BY INDEX ROWID | MM_WRITEOUT_TO                |       |       |       |:: |        |       |       |          |
|*  |             INDEX UNIQUE SCAN          | PK_MM_WRITEOUT_TO             |       |       |       |:: |        |       |       |          |
|   |           TABLE ACCESS BY INDEX ROWID  | MM_INPAYMENT_TD               |       |       |       |:: |        |       |       |          |
|*  |            INDEX UNIQUE SCAN           | PK_MM_INPAYMENT_TD            |       |       |       |:: |        |       |       |          |
|*  |          TABLE ACCESS BY INDEX ROWID   | MM_PAYMENTIN_EVENTS_TD        |       |       |       |:: |       |       |       |          |
|*  |           INDEX RANGE SCAN             | IDX_PAYMENTINE_08             |       |      |     |:: |        |       |       |          |
|   |         SORT UNIQUE                    |                               |       |       |       |:: |        |  |  |          |
|*  |          INDEX RANGE SCAN              | IDX_PAYMENTINE_TEST           |       |       |       |:: |        |       |       |          |
|   |        TABLE ACCESS BY INDEX ROWID     | MM_PAYABLEMONEY_TD            |       |       |       |:: |        |       |       |          |
|*  |         INDEX UNIQUE SCAN              | PK_MM_PAYABLEMONEY_TD         |       |       |       |:: |        |       |       |          |
|   |       TABLE ACCESS BY INDEX ROWID      | MM_BATCHINFO_TD               |       |       |       |:: |        |       |       |          |
|*  |        INDEX RANGE SCAN                | IDX_BATCH_TD_SERIALNO         |       |       |       |:: |        |       |       |          |
|*  |      INDEX RANGE SCAN                  | IDX_BATCHINFO_TI_01           |       |       |       |:: |        |       |       |          |
|*  |     INDEX RANGE SCAN                   | IDX_MM_SAP_VOUCHER_DETAIL_TO1 |       |    |       |:: |        |       |       |          |
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   - access((("S"."STATUS"='00' OR "S"."STATUS"='XX')) AND "S"."BATCH_ID"='1219639828')
   - access("T1"."ID"="S"."ID")
   - access("T2"."INPAYMENTID"=TO_NUMBER("T1"."BUSINESSNO"))
   - access("T3"."NEWNO"="T2"."INPAYMENTID")
   - access("T3"."OLDNO"="T4"."PAYABLENO")
   - access("T5"."OPSTATUS"='0' AND "T5"."SERIALNO"="T4"."CUSTSEQ")
   - access("T6"."STATUS"='2' AND "T6"."ID"="T5"."SEQBATCH")
   - access("O"."DAILYAUDITNO"="T3"."DAILYAUDITNO")
       filter("T2"."INPAYMENTID"=TO_NUMBER("O"."BUSINESSNO"))
   - access((("S"."STATUS"='00' OR "S"."STATUS"='XX')) AND "S"."BATCH_ID"='1219639828')
   - access("T1"."ID"="S"."ID")
   - access("T2"."INPAYMENTID"=TO_NUMBER("T1"."BUSINESSNO"))
   - filter("T3"."FATHERNO" IS NOT NULL)
   - access("T3"."NEWNO"="T2"."INPAYMENTID")
   - access("P"."LISTNO"="T3"."FATHERNO")
   - access("T4"."PAYABLENO"="P"."OLDNO")
   - access("T5"."OPSTATUS"='0' AND "T5"."SERIALNO"="T4"."CUSTSEQ")
   - access("T6"."STATUS"='2' AND "T6"."ID"="T5"."SEQBATCH")
   - access("O"."DAILYAUDITNO"="T3"."DAILYAUDITNO")
       filter("T2"."INPAYMENTID"=TO_NUMBER("O"."BUSINESSNO"))

           
代入最新值,秒出結果。

後經開發檢驗,該sql大大改善了系統性能,cpu使用率也随之下降。