Re: How to fix cache buffer chain issue

  • From: Pap <oracle.developer35@xxxxxxxxx>
  • To: Jonathan Lewis <jlewisoracle@xxxxxxxxx>, Andy Sayer <andysayer@xxxxxxxxx>
  • Date: Mon, 28 Jun 2021 00:07:44 +0530

Thank you very much Jonathan and Andrew.

I had modified the query as per Jonathan's suggestion and tested by
converting the first four UNION clauses. The results matching and also the
modified query access path does show only one time access to the
table/indexes of TAD/TAD_Ix2. Attached is the modified query with its
sqlmonitor.

Andrew, for my understanding here, I think you got the HASH JOIN access of
TAD clue from below plan, but i am still not able to understand how this
path suggests the HASH JON access of TAD, as because line 9 and 10 shows
two nested loops and HASH Join is in third position in the tree. So I am
assuming line 9- i.e first nested loop JOIN is between TNI and TMTD and
line 10 is for the join between TAD and the result set out of TNI JOIN
TMTD. So doesn't it mean that table TAD is also accessed in a nested loop
path here? Please guide me here. However, as you suggested,  I simply tried
the option i.e. forcing a HASH Join path through profile , for all SELECT
queries. This way too the query is giving us results in less than minutes
as opposed to ~15-20minutes with the all NESTED LOOP access path. And to
answer your earlier question, here table TNI is a global temporary table
and XX is a literal used in the query as filter, but yes as it's a global
temporary table we are relying on dynamic sampling here and sometimes it
goes off quite a bit more than actual cardinality and that is possibly
causing different execution path.



----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name
 | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                       |
  |       |       | 12967 (100)|          |
|   1 |  LOAD TABLE CONVENTIONAL               |
  |       |       |            |          |
|   2 |   SORT UNIQUE                          |
  |    18 |  1548 | 12967   (1)| 00:02:36 |
|   3 |    UNION-ALL                           |
  |       |       |            |          |
|   4 |     HASH GROUP BY                      |
  |     1 |    86 |   738   (1)| 00:00:09 |
|   5 |      NESTED LOOPS                      |
  |     1 |    86 |   736   (1)| 00:00:09 |
|   6 |       NESTED LOOPS                     |
  |     1 |    86 |   736   (1)| 00:00:09 |
|   7 |        NESTED LOOPS                    |
  |     1 |    79 |   735   (1)| 00:00:09 |
|*  8 |         HASH JOIN                      |
  |     1 |    60 |   734   (1)| 00:00:09 |
|   9 |          NESTED LOOPS                  |
  |    12 |   384 |    26   (0)| 00:00:01 |
|  10 |           NESTED LOOPS                 |
  |    12 |   384 |    26   (0)| 00:00:01 |
|* 11 |            TABLE ACCESS STORAGE FULL   | TNI
  |    12 |   192 |     2   (0)| 00:00:01 |
|* 12 |            INDEX UNIQUE SCAN           | MTD_PK
 |     1 |       |     1   (0)| 00:00:01 |
|  13 |           TABLE ACCESS BY INDEX ROWID  | TMTD
 |     1 |    16 |     2   (0)| 00:00:01 |



*|* 14 |          TABLE ACCESS BY INDEX ROWID   | TAD
  |    14 |   392 |   708   (1)| 00:00:09 ||* 15 |           INDEX RANGE
SCAN             | TAD_IX2                     | 28797 |       |   116
(0)| 00:00:02 ||  16 |            SORT AGGREGATE              |
                |     1 |     8 |            |          ||  17 |
  INDEX FULL SCAN (MIN/MAX)  | TAD_IX2                     |     1 |     8
|     3   (0)| 00:00:01 |*
|  18 |         TABLE ACCESS BY INDEX ROWID    | TMMC
 |     1 |    19 |     1   (0)| 00:00:01 |
|* 19 |          INDEX RANGE SCAN              | TMMC_IX1
 |     1 |       |     0   (0)|          |
|* 20 |        INDEX UNIQUE SCAN               | MCT_PK
 |     1 |       |     0   (0)|          |
|  21 |       TABLE ACCESS BY INDEX ROWID      | TMCT
 |     1 |     7 |     1   (0)| 00:00:01 |
|  22 |     HASH GROUP BY                      |
  |     1 |    86 |   717   (1)| 00:00:09 |



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

   8 - access("TMTD"."PMENT"="TAD"."PMENT")
  11 - storage("TNI"."NE"='XX')
       filter("TNI"."NE"='XX')
  12 - access("TNI"."NID"="TMTD"."DID")
  14 - filter(((NVL(:B1,'ZZZZ')='ZZZZ' OR ("TAD"."MCD"=:B1 AND
NVL(:B1,'ZZZZ')<>'ZZZZ')) AND
              TRUNC(:B2)-"ADT"<=1))
  15 - access("TAD"."DT_CR"=)
  19 - access("TAD"."MCD"="TMMC"."PTMCD")
  20 - access("TMTD"."CID"="TMCT"."SWCTID")

Regards
Pap

On Thu, Jun 24, 2021 at 3:34 PM Jonathan Lewis <jlewisoracle@xxxxxxxxx>
wrote:

It's up to you to check the validaty of my guess regarding the nature of
the query simply breaking a data set for a given date by different ranges
then the basis of the mechanism is to take the predicate (list) that breaks
the data set into pieces and combine the list in a CASE expression that
generates a value that can be used as an extra grouping column, along the
lines of:

select
        case
                when adt - to_date(:b1,'yyyy-mm-dd') <= 1
                        then 'g1'
                when adt - to_date(:b1,'yyyy-mm-dd')  > 1 and adt -
to_date(:b1,'yyyy-mm-dd') <= 2 then 'g2'
                when adt - to_date(:b1,'yyyy-mm-dd')  > 2 and adt -
to_date(:b1,'yyyy-mm-dd') <= 7 then 'g3'
                when adt - to_date(:b1,'yyyy-mm-dd')  > 7
                        then 'g4'
        end flag,
        mcd,
        sum(value_col), count(*)
from
        v1
group by
        case
                when adt - to_date(:b1,'yyyy-mm-dd') <= 1
                        then 'g1'
                when adt - to_date(:b1,'yyyy-mm-dd')  > 1 and adt -
to_date(:b1,'yyyy-mm-dd') <= 2 then 'g2'
                when adt - to_date(:b1,'yyyy-mm-dd')  > 2 and adt -
to_date(:b1,'yyyy-mm-dd') <= 7 then 'g3'
                when adt - to_date(:b1,'yyyy-mm-dd')  > 7
                        then 'g4'
        end,
        mcd
order by
        flag, mcd
/


Regards
Jonathan Lewis

On Tue, 22 Jun 2021 at 19:16, Pap <oracle.developer35@xxxxxxxxx> wrote:

Thanks much Jonathan.

Trying to visualize/understand the code modification which you suggested.
Agreed that the difference in the query is just the date criteria filter on
column ADT of table TAD. But currently we are fetching sum(amt) and
count(*) based on the grouping column in each of those queries.




SELECT 
TAD.MCD,
     TMMC.PMCDVAL,
CASE WHEN  (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 1 then 'G1'
     WHEN   (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 1
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 2 then 'G2'
                         WHEN   (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 2
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 3 then 'G3'
                         WHEN   (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 3
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 4 then 'G4'
                        end flag,
     SUM(CASE WHEN  (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 1 then AMT
              WHEN   (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 1
              AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 2 then AMT 
                          WHEN   (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 2
              AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 3 then AMT 
                          WHEN   (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 3
              AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 4 then AMT 
             end 
             )
                          amount,
                         SUM(CASE WHEN  (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - 
ADT) <= 1 then 1
                 WHEN   (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 1
                       AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 2 
then 1 
                                           WHEN   (TRUNC ( 
to_date(:B2,'DD-MON-YYYY')) - ADT) > 2
                       AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 3 
then 1 
                                           WHEN   (TRUNC ( 
to_date(:B2,'DD-MON-YYYY')) - ADT) > 3
                       AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 4 
then 1 
                            end ) count_1,
            :B3,
            TMCT.PDCMLPNT,
            TMTD.PMENT
 FROM TAD TAD,
                TMMC TMMC,
                TMTD TMTD,
                TMCT TMCT
      WHERE     TAD.MCD = TMMC.PTMCD
            AND TMTD.PMENT = TAD.PMENT
            AND TMTD.CID = TMCT.SWCTID
           AND (
                   ((TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 1 )
                      OR ((TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 1
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 2)
                        OR ((TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 2
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 3)
                        OR ((TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 3
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 4)
                        )
            AND (   (TAD.MCD = :B1 AND NVL ( :B1, 'ZZZZ') <> 'ZZZZ')
                 OR NVL ( :B1, 'ZZZZ') = 'ZZZZ')
            AND TAD.DT_CR IN (SELECT MAX (DT_CR)
                                FROM TAD)
   GROUP BY TMTD.PMENT,
            TAD.MCD,
            TMMC.PMCDVAL,
            TMCT.PDCMLPNT       ,
        CASE WHEN  (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 1 then 'G1'
            WHEN (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 1
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 2 then 'G2'
                        WHEN (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 2
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 3 then 'G3'
                        WHEN (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) > 3
            AND (TRUNC ( to_date(:B2,'DD-MON-YYYY')) - ADT) <= 4 then 'G4' end 
         order by flag
         
         
         

Global Information
------------------------------
 Status              :  DONE (ALL ROWS)           
 Instance ID         :  4                         
 SQL ID              :  00tvurfdd4cm7             
 SQL Execution ID    :  67108864                  
 Execution Started   :  06/27/2021 13:46:45       
 First Refresh Time  :  06/27/2021 13:46:45       
 Last Refresh Time   :  06/27/2021 13:46:45       
 Duration            :  .106346s                  
 Module/Action       :  SQL*Plus/-                
 Program             :  sqlplus.exe               
 Fetch Calls         :  2                         

Binds
========================================================================================================================
| Name | Position |      Type      |                                       
Value                                       |
========================================================================================================================
| :B2  |        1 | VARCHAR2(4001) | 17-jun-2021                                
                                       |
| :B1  |       30 | VARCHAR2(4001) | ZZZZ                                       
                                       |
========================================================================================================================

Global Stats
=========================================================================================
| Elapsed |   Cpu   |    IO    | Concurrency | Cluster  | Fetch | Buffer | Read 
| Read  |
| Time(s) | Time(s) | Waits(s) |  Waits(s)   | Waits(s) | Calls |  Gets  | Reqs 
| Bytes |
=========================================================================================
|    0.11 |    0.06 |     0.01 |        0.00 |     0.04 |     2 |  23167 |   14 
| 112KB |
=========================================================================================

SQL Plan Monitoring Details (Plan Hash Value=4294317510)
===================================================================================================================================================================================================
| Id |              Operation               |            Name             |  
Rows   | Cost |   Time    | Start  | Execs |   Rows   | Read | Read  |  Mem  | 
Activity |      Activity Detail       |
|    |                                      |                             | 
(Estim) |      | Active(s) | Active |       | (Actual) | Reqs | Bytes | (Max) | 
  (%)    |        (# samples)         |
===================================================================================================================================================================================================
|  0 | SELECT STATEMENT                     |                             |     
    |      |         1 |     +0 |     1 |      529 |      |       |       |     
     |                            |
|  1 |   SORT GROUP BY                      |                             |     
 15 |  797 |         1 |     +0 |     1 |      529 |      |       | 67584 |     
     |                            |
|  2 |    NESTED LOOPS                      |                             |     
 15 |  796 |         1 |     +0 |     1 |     5997 |      |       |       |     
     |                            |
|  3 |     NESTED LOOPS                     |                             |     
 15 |  796 |         1 |     +0 |     1 |     5997 |      |       |       |     
     |                            |
|  4 |      HASH JOIN                       |                             |     
 15 |  781 |         1 |     +0 |     1 |     5997 |      |       |    1M |     
     |                            |
|  5 |       NESTED LOOPS                   |                             |     
 15 |  779 |         1 |     +0 |     1 |     5997 |      |       |       |     
     |                            |
|  6 |        NESTED LOOPS                  |                             |     
 17 |  779 |         1 |     +0 |     1 |     5997 |      |       |       |     
     |                            |
|  7 |         TABLE ACCESS BY INDEX ROWID  | TAD                         |     
 17 |  728 |         1 |     +0 |     1 |     5997 |      |       |       |     
     |                            |
|  8 |          INDEX RANGE SCAN            | TAD_IX2                     |   
29513 |  119 |         1 |     +0 |     1 |     8659 |      |       |       |   
100.00 | gc current block 3-way (1) |
|  9 |           SORT AGGREGATE             |                             |     
  1 |      |         1 |     +0 |     1 |        1 |      |       |       |     
     |                            |
| 10 |            INDEX FULL SCAN (MIN/MAX) | TAD_IX2                     |     
  1 |    3 |         1 |     +0 |     1 |        1 |      |       |       |     
     |                            |
| 11 |         INDEX RANGE SCAN             | TMTD_IX2                    |     
  1 |    2 |         1 |     +0 |  6183 |     5997 |    4 | 32768 |       |     
     |                            |
| 12 |        TABLE ACCESS BY INDEX ROWID   | TMTD                        |     
  1 |    3 |         1 |     +0 |  6114 |     5997 |    5 | 40960 |       |     
     |                            |
| 13 |       VIEW                           | index$_join$_002            |     
110 |    2 |         1 |     +0 |     1 |      112 |      |       |       |     
     |                            |
| 14 |        HASH JOIN                     |                             |     
    |      |         1 |     +0 |     1 |      112 |      |       |    2M |     
     |                            |
| 15 |         INDEX STORAGE FAST FULL SCAN | MMC_IX1                     |     
110 |    1 |         1 |     +0 |     1 |      112 |      |       |       |     
     |                            |
| 16 |         INDEX STORAGE FAST FULL SCAN | MMC_IX2                     |     
110 |    1 |         1 |     +0 |     1 |      112 |      |       |       |     
     |                            |
| 17 |      INDEX UNIQUE SCAN               | MCT_PK                      |     
  1 |      |         1 |     +0 |  5997 |     5997 |      |       |       |     
     |                            |
| 18 |     TABLE ACCESS BY INDEX ROWID      | TMCT                        |     
  1 |    1 |         1 |     +0 |  5997 |     5997 |      |       |       |     
     |                            |
===================================================================================================================================================================================================
Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("TAD"."MCD"="TMMC"."PTMCD")
   7 - filter(("TAD"."MCD"=:B1 AND NVL(:B1,'ZZZZ')<>'ZZZZ' OR 
NVL(:B1,'ZZZZ')='ZZZZ') AND
              (TRUNC(TO_DATE(:B2,'DD-MON-YYYY'))-"ADT"<=1 OR 
TRUNC(TO_DATE(:B2,'DD-MON-YYYY'))-"ADT">1 AND
              TRUNC(TO_DATE(:B2,'DD-MON-YYYY'))-"ADT"<=2 OR 
TRUNC(TO_DATE(:B2,'DD-MON-YYYY'))-"ADT">2 AND
              TRUNC(TO_DATE(:B2,'DD-MON-YYYY'))-"ADT"<=3 OR 
TRUNC(TO_DATE(:B2,'DD-MON-YYYY'))-"ADT">3 AND
              TRUNC(TO_DATE(:B2,'DD-MON-YYYY'))-"ADT"<=4))
   8 - access("TAD"."DT_CR"= (SELECT MAX("DT_CR") FROM "SCHEMA1"."TAD"
              "TAD"))
  11 - access("TMTD"."PMENT"="TAD"."PMENT")
  14 - access(ROWID=ROWID)
  17 - access("TMTD"."CID"="TMCT"."SWCTID")

Other related posts: