Re: Query Performance Issue
From: Pap <oracle.developer35_at_gmail.com>
Date: Wed, 3 Nov 2021 23:00:24 +0530
Message-ID: <CAEjw_fiBBX2f-jnLsmpO5D4JhWwUC+uAHw7wgtaXrbjTTtmGBw_at_mail.gmail.com>
> What is the outcome if you add the hint /*+ leading(RDC) */ in your query?
> Thanks.
> În mie., 3 nov. 2021 la 05:05, Pap <oracle.developer35_at_gmail.com> a scris:
Date: Wed, 3 Nov 2021 23:00:24 +0530
Message-ID: <CAEjw_fiBBX2f-jnLsmpO5D4JhWwUC+uAHw7wgtaXrbjTTtmGBw_at_mail.gmail.com>
This contains a global temporary table so I was not able to run it isolated from outside in prod. But if i tried to give the cardinality hint for the global temp table and run the query with full(RDC) hint the plan looks as below. It has a bunch of odd things like merge cartesian, buffer sort, index skip scan etc. So I'm wondering if it will really help or make this ~7second query worse.
| Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 53 | 5220 (1)| 00:00:01 | | 1 | VIEW | VM_NWVW_1 | 1 | 53 | 5220 (1)| 00:00:01 | | 2 | HASH UNIQUE | | 1 | 127 | 5220 (1)| 00:00:01 | | 3 | NESTED LOOPS SEMI | | 1 | 127 | 5219 (1)| 00:00:01 | | 4 | MERGE JOIN CARTESIAN | | 1 | 112 | 5217 (1)| 00:00:01 | |* 5 | HASH JOIN | | 1 | 99 | 5215 (1)| 00:00:01 | |* 6 | TABLE ACCESS STORAGE FULL | RDC | 394 | 22852 | 176 (1)| 00:00:01 | |* 7 | TABLE ACCESS BY INDEX ROWID BATCHED| RFCER | 1 | 41 | 5039 (1)| 00:00:01 | |* 8 | INDEX SKIP SCAN | RFCER_IX2 | 8612 | | 1242 (0)| 00:00:01 | | 9 | BUFFER SORT | | 1 | 13 | 178 (1)| 00:00:01 | | 10 | TABLE ACCESS STORAGE FULL | RTNI | 1 | 13 | 2 (0)| 00:00:01 | |* 11 | TABLE ACCESS BY INDEX ROWID | RDCH | 234K| 3433K| 2 (0)| 00:00:01 | |* 12 | INDEX UNIQUE SCAN | RDCH_PK | 1 | | 1(0)| 00:00:01 |
On Wed, Nov 3, 2021 at 1:44 PM Laurentiu Oprea <laurentiu.oprea06_at_gmail.com> wrote:
> Hello,
>
> What is the outcome if you add the hint /*+ leading(RDC) */ in your query?
>
> Thanks.
>
> În mie., 3 nov. 2021 la 05:05, Pap <oracle.developer35_at_gmail.com> a scris:
>
>>
>> Thank you Sayan. Below is the output for the asked queries and the DDL
>> and statistics information. And yes the column SCD and DCC itself does not
>> have the '/' character in them but the incoming literal does have that '/'
>> character to match with the concatenated LHS. And the input literal on the
>> right hand side varies each time.
>>
>> I am not sure how line 10 and 11 is operating/getting estimated here in
>> the plan. But that table has no histogram on column CTD and that is why
>> perhaps the estimation becomes 702k/3=302K. But the actual number of values
>> with filter CT_CD= 'XX' is resulting in ~50K rows from that table. So do
>> you think adding histogram to this column will help in getting us a
>> better/faster execution path?
>>
>> select count(*) from RFCER;
>>
>> --4228120
>>
>> select count(*) c1, count(distinct CKEY) c2
>> , count(case when CLKEY=20211001 and AFRI='ZZZZ' then 1 end) c3
>> , count(case when CLKEY=20211001 then 1 end) c4
>> , count(case when AFRI='ZZZZ' then 1 end) c5
>> from RFCER
>> where CLKEY=20211001 or AFRI='ZZZZ';
>>
>> C1 C2 C3 C4 C5
>> 3991390 1240 8409 8891 3990908
>>
>> select count(*) from RDC;
>>
>> --39093
>>
>> select count(*),length(SCD),length(DCC)
>> from RDC
>> where RDC.SCD || '/' || RDC.DCC = 'AAAAAA'
>> group by length(SCD),length(DCC);
>>
>> COUNT(*) LENGTH(SRC_CURRENCY_CD) LENGTH(DEST_CURRENCY_CD)
>> 1 3 3
>>
>> ********** DDL And Statistics******************
>>
>> DDL:-
>>
>> CREATE TABLE RFCER
>> (
>> CKEY NUMBER,
>> ERKEY NUMBER NOT NULL,
>> CLKEY NUMBER NOT NULL,
>> CR_KEY NUMBER NOT NULL,
>> AFRI VARCHAR2(38 BYTE) DEFAULT 'NONE' NOT NULL)
>>
>> CREATE INDEX RFCER_IX2 ON RFCER(CKEY, CLKEY, CR_KEY);
>> CREATE UNIQUE INDEX RFCER_PK ON RFCER(ERKEY);
>> ALTER TABLE RFCER ADD ( CONSTRAINT RFCER_PK PRIMARY KEY (ERKEY) USING
>> INDEX RFCER_PK ENABLE VALIDATE);
>>
>> Table Num_rows = 4219207
>>
>> INDEX_NAME BLEVEL DISTINCT_KEYS CLUSTERING_FACTOR NUM_ROWS SAMPLE_SIZE
>> RFCER_IX2 2 3884057 1899024 4164177 168817
>>
>> TABLE_NAME COLUMN_NAME NUM_DISTINCT DENSITY NUM_NULLS
>> RFCER CKEY 1240 0.000806451612903226 0
>> RFCER CLKEY 490 0.00204081632653061 0
>> RFCER CR_KEY 543 0.00184162062615101 0
>> RFCER AFRI 235024 4.25488460752944E-6 0
>>
>>
>> *****************
>>
>> CREATE TABLE RDC
>> (
>> CR_KEY INTEGER CONSTRAINT RDC_C01 NOT NULL,
>> SCD VARCHAR2(3 BYTE),
>> DCC VARCHAR2(3 BYTE),
>> SCDSC VARCHAR2(30 BYTE),
>> DCDSC VARCHAR2(30 BYTE)
>> );
>> CREATE INDEX RDC_IX1 ON RDC(DCC, SCD);
>> CREATE UNIQUE INDEX RDC_PK ON RDC(CR_KEY);
>> ALTER TABLE RDC ADD ( CONSTRAINT RDC_PK PRIMARY KEY (CR_KEY) USING INDEX
>> RDC_PK ENABLE VALIDATE);
>>
>> Table Num_rows= 39110
>>
>> INDEX_NAME BLEVEL DISTINCT_KEYS CLUSTERING_FACTOR NUM_ROWS SAMPLE_SIZE
>> RDC_IX1 1 36100 31811 39093
>> 39093
>>
>> INDEX_NAME BLEVEL DISTINCT_KEYS CLUSTERING_FACTOR NUM_ROWS SAMPLE_SIZE
>> RDC_PK 1 39093 5834 39093 39093
>>
>> TABLE_NAME COLUMN_NAME NUM_DISTINCT DENSITY NUM_NULLS
>> RDC SCD 190 0.00526315789473684 0
>> RDC DCC 190 0.00526315789473684 0
>>
>> *********************
>>
>> Table RDCH holds a total ~702K records. It has a composite index -
>> RDCH_IX1 on column (CT_CD,CID) and another index on column (CID).
>>
>> INDEX_NAME BLEVEL DISTINCT_KEYS CLUSTERING_FACTOR NUM_ROWS SAMPLE_SIZE
>> RDCH_IX1 2 702344 477946 702344 702344
>>
>> INDEX_NAME BLEVEL DISTINCT_KEYS CLUSTERING_FACTOR NUM_ROWS SAMPLE_SIZE
>> RDCH_IX9 2 554752 557317 702344 702344
>>
>> TABLE_NAME COLUMN_NAME NUM_DISTINCT DENSITY NUM_NULLS
>> RDCH CID 554752 1.80260729118597E-6 0
>> RDCH CT_CD 3 0.333333333333333 0
>>
>>
>> On Wed, Nov 3, 2021 at 5:05 AM Sayan Malakshinov <xt.and.r_at_gmail.com>
>> wrote:
>>
>>> Hi Pap,
>>>
>>> You haven't provided enough info for complete analysis. It would be
>>> better if you provide DDL of all those tables with all their indexes, and
>>> table statistics.
>>> Also IFFS by RDCH_PK (plan line #11) shows 234k rows estimated, though
>>> it returns 702k rows == 3 times more than estimated, so probably you need
>>> to actualize your statistics.
>>> Can RDC.SCD or RDC.DCC contain '/' characters? (I understand that you
>>> can't show real data, but it's better to provide literals more similar to
>>> real - obviously RDC.SCD || '/' || RDC.DCC = 'AAAAAA' can't be true).
>>> And show please what do return these queries:
>>>
>>> select count(*) from RFCER;
>>>
>>> select count(*) c1, count(distinct CKEY) c2
>>> , count(case when CLKEY=20211001 and AFRI='ZZZZ' then 1 end) c3
>>> , count(case when CLKEY=20211001 then 1 end) c4
>>> , count(case when AFRI='ZZZZ' then 1 end) c5
>>> from RFCER
>>> where CLKEY=20211001 or AFRI='ZZZZ';
>>>
>>> select count(*) from RDC;
>>>
>>> select count(*)
>>> ,length(SCD)
>>> ,length(DCC)
>>> from RDC
>>> where RDC.SCD || '/' || RDC.DCC = 'AAAAAA'
>>> group by length(SCD),length(DCC);
>>>
>>>
>>> On Tue, Nov 2, 2021 at 10:18 PM Pap <oracle.developer35_at_gmail.com>
>>> wrote:
>>>
>>>> Hi , It's an oracle 19C database. We have the below query which runs
>>>> ~7-10seconds per execution and we want to see if we can further make the
>>>> improvement in run time someway. it's called thousands of times in a
>>>> process because of certain design limitations of a third party app, so the
>>>> number of executions can't be minimized to once per process. So we are
>>>> trying to see what we can do to minimize the run time per execution for
>>>> this query.
>>>>
>>>> As per ASH the major amount of time spent in plan_line_id 12 and 13
>>>> i.e. scanning of table RFCER. And in sql monitor that shows ~4K+ executions
>>>> for that line and its matching with the number of rows in table RTNI. Then
>>>> the second highest time is spent on plan_line_id 14 and 15 which shows
>>>> ~1million execution. Here table RTNI is a global temporary table which is
>>>> populated during run time. So want to understand what we can do to improve
>>>> the run time for this query?
>>>>
>>>> SELECT RDC.SCD, RDC.SCDSC , RDC.DCC, RDC.DCDSC , ERATE
>>>> FROM RFCER ,
>>>> ( SELECT DISTINCT RDCH.CKEY
>>>> FROM RTNI , RDCH
>>>> WHERE TO_CHAR (RTNI.MCI) = RDCH.CID
>>>> AND RDCH.CT_CD = 'XX') RTNI,
>>>> RDC
>>>> WHERE RFCER.CKEY = RTNI.CKEY
>>>> AND RFCER.AFRI = 'ZZZZ'
>>>> AND CLKEY = 20211001
>>>> AND RFCER.CR_KEY = RDC.CR_KEY
>>>> AND RDC.SCD || '/' || RDC.DCC = 'AAAAAA';
>>>>
>>>> Thinking if converting the Distinct inline query using below EXISTS
>>>> operator will help anyway?
>>>>
>>>> (SELECT RDCH.CKEY
>>>> FROM RDCH RDCH
>>>> WHERE RDCH.CT_CD = 'XX'
>>>> AND EXISTS
>>>> (SELECT 'X'
>>>> FROM RTNI RTNI
>>>> WHERE TO_CHAR (RTNI.MCI) = RDCH.CID)) RTNI
>>>>
>>>>
>>>> Global Information
>>>> ------------------------------
>>>> Status : DONE (ALL ROWS)
>>>> Instance ID : 2
>>>> SQL ID : 3dfmkcu292v30
>>>> SQL Execution ID : 33555042
>>>> Execution Started : 11/01/2021 22:11:49
>>>> First Refresh Time : 11/01/2021 22:11:55
>>>> Last Refresh Time : 11/01/2021 22:11:56
>>>> Duration : 7s
>>>> Fetch Calls : 1
>>>>
>>>> Global Stats
>>>> =================================================
>>>> | Elapsed | Cpu | Other | Fetch | Buffer |
>>>> | Time(s) | Time(s) | Waits(s) | Calls | Gets |
>>>> =================================================
>>>> | 6.95 | 6.85 | 0.10 | 1 | 3M |
>>>> =================================================
>>>>
>>>> SQL Plan Monitoring Details (Plan Hash Value=3330725745)
>>>>
>>>> ==================================================================================================================================================================================
>>>> | Id | Operation | Name
>>>> | Rows | Cost | Time | Start | Execs | Rows | Mem
>>>> | Activity | Activity Detail |
>>>> | | |
>>>> | (Estim) | | Active(s) | Active | | (Actual) | (Max)
>>>> | (%) | (# samples) |
>>>>
>>>> ==================================================================================================================================================================================
>>>> | 0 | SELECT STATEMENT |
>>>> | | | | | 1 | | .
>>>> | | |
>>>> | 1 | VIEW | VM_NWVW_1
>>>> | 3 | 7616 | | | 1 | | .
>>>> | | |
>>>> | 2 | HASH UNIQUE |
>>>> | 3 | 7616 | | | 1 | | .
>>>> | | |
>>>> | 3 | NESTED LOOPS |
>>>> | 3 | 7615 | 2 | +6 | 1 | 0 | .
>>>> | | |
>>>> | 4 | NESTED LOOPS |
>>>> | 3 | 7615 | 2 | +6 | 1 | 1M | .
>>>> | | |
>>>> | 5 | NESTED LOOPS |
>>>> | 3 | 7612 | 2 | +6 | 1 | 1M | .
>>>> | | |
>>>> | 6 | HASH JOIN |
>>>> | 2080 | 3437 | 2 | +6 | 1 | 4007 | 3MB
>>>> | | |
>>>> | 7 | TABLE ACCESS STORAGE FULL | RTNI
>>>> | 4335 | 30 | 1 | +6 | 1 | 4007 |
>>>> . | | |
>>>> | 8 | VIEW | index$_join$_004
>>>> | 234K | 3406 | 2 | +6 | 1 | 50883 |
>>>> . | | |
>>>> | 9 | HASH JOIN |
>>>> | | | 2 | +6 | 1 | 50883 | 7MB
>>>> | | |
>>>> | 10 | INDEX RANGE SCAN | RDCH_IX1
>>>> | 234K | 857 | 1 | +6 | 1 | 50883 |
>>>> . | | |
>>>> | 11 | INDEX STORAGE FAST FULL SCAN | RDCH_PK
>>>> | 234K | 1779 | 2 | +6 | 1 | 702K | .
>>>> | | |
>>>> | 12 | TABLE ACCESS BY INDEX ROWID BATCHED | RFCER
>>>> | 1 | 6 | 5 | +3 | 4007 | 1M | .
>>>> | | |
>>>> | 13 | INDEX RANGE SCAN | RFCER_IX2
>>>> | 7 | 2 | 4 | +4 | 4007 | 1M | .
>>>> | | |
>>>> | 14 | INDEX UNIQUE SCAN | RDC_PK
>>>> | 1 | | 6 | +2 | 1M | 1M |
>>>> . | | |
>>>> | 15 | TABLE ACCESS BY INDEX ROWID | RDC
>>>> | 1 | 1 | 1 | +1 | 1M | 0 | .
>>>> | | |
>>>>
>>>> ==================================================================================================================================================================================
>>>>
>>>> Predicate Information (identified by operation id):
>>>> ---------------------------------------------------
>>>> 6 - access("RDCH"."CID"=TO_CHAR("RTNI"."MCI"))
>>>> 8 - filter("RDCH"."CT_CD"='XX')
>>>> 9 - access(ROWID=ROWID)
>>>> 10 - access("RDCH"."CT_CD"='XX')
>>>> 12 - filter("RFCER"."AFRI"='ZZZZ')
>>>> 13 - access("RFCER"."CKEY"="RDCH"."CKEY" AND "CLKEY"=20211001)
>>>> 14 - access("RFCER"."CR_KEY"="RDC"."CR_KEY")
>>>> 15 - filter("RDC"."SCD"||'/'||"RDC"."DCC"='AAAAAA')
>>>>
>>>
>>>
>>> --
>>> Best regards,
>>> Sayan Malakshinov
>>> Oracle performance tuning engineer
>>> Oracle ACE Associate
>>> http://orasql.org
>>>
>>
-- http://www.freelists.org/webpage/oracle-lReceived on Wed Nov 03 2021 - 18:30:24 CET
