RE: Need help in SQL tunning

From: Mark W. Farnham <mwf_at_rsiz.com>
Date: Sat, 22 Oct 2022 07:38:45 -0400
Message-ID: <09c001d8e60a$d8964da0$89c2e8e0$_at_rsiz.com>



As JL noted, an explanation of the logic from your application team is needed. I suggest you hand them my examples, because I think it is highly likely the code does not do what they think it does.  

(I’ve never actually seen these three classic misunderstandings combined in a single query before: 1) The mistake that “LEFT JOIN” is different from “LEFT OUTER JOIN” (which is implicitly their belief by having b.<anything> as a predicate in the correlated subquery), 2) The mistake that if you access by an index without an order by you are guaranteed a result sorted in the order of the index and that if you have a sensible index it will always be chosen (this mistake is implicit because of rownum as a variable predicate, unless they mean to get only a single row and don’t care which row, in which case the code is clearer supplying the constant 1), and 3) that any equality predicate of rownum other than 1 can return any rows (implicit in using a variable.  

Sigh.  

IF it is doing what they think it does, then I wonder WHY they would so obscure the logic. The first step of tuning is whether or not the code produces the intended results.  

Good luck. Perhaps JL will chime in if my explanation is unclear.  

mwf  

From: oracle-l-bounce_at_freelists.org [mailto:oracle-l-bounce_at_freelists.org] On Behalf Of Krishnaprasad Yadav Sent: Saturday, October 22, 2022 1:42 AM To: Mark W. Farnham
Cc: Oracle L
Subject: Re: Need help in SQL tunning  

Hi Mark,  

Thanks for sharing your views , its really helpful  

Since I was in a situation where I see a tuning advisor provides me benefits instantly rather than rewriting the query which application team take some time to change the code probably day or 2 .  

so for time being i used recommendation from advisor  

but yes , i am curious to know what changes optimizer is doing to get the plan , since i too tried with some hints , but i feel predicate b.col_name=val is getting transformed somehow , even i tried unnesting subquery too, but landed in no luck  

Regards,

Krishna                    

On Sat, 22 Oct 2022 at 04:16, Mark W. Farnham <mwf_at_rsiz.com> wrote:

PS: I did all this early this morning, so I didn’t see the comments of the others, which are more about your existing query.  

I still think my re-write is iso-functional and what you should do, but maybe someone can point out a flaw.  

mwf  

From: oracle-l-bounce_at_freelists.org [mailto:oracle-l-bounce_at_freelists.org] On Behalf Of Mark W. Farnham Sent: Friday, October 21, 2022 6:20 PM
To: chrishna0007_at_gmail.com; 'Oracle L' Subject: RE: Need help in SQL tunning  

Not answering your question, but puzzled…  

select a.status, b.status from a left join b

on b.name = a.name  

would be the outer join.  

but then, you only want the rows returned when  

a.c_id in (select id from c where b.name =: <a value>….)  

now any no-match between a and b on name is going to return NULL for the value of b.name, that being the nature of outer joins.  

That makes me wonder why you don’t prune a first, before the join, and then equijoin the pruned a with b where a.name = b.name.  

further, any other value than 1 for sys_b_2 won’t get any rows, so it seems strange to use a variable there when using 1 would give the CBO more information. (If the application is going to submit for any other rownum than 1, simply don’t run the query.  

Trivial example (which I think is version invariant):  

SQL> r

  1 select a.status astat, b.status bstat, a.name aname, b.name bname

  2 from a left join b

  3 on b.name = a.name

  4 where a.c_id in (

  5 select id from c

  6 where b.name = 'one'

  7 )

  8* and rownum = 2  

no rows selected  

SQL> c/2/1

  8* and rownum = 1

SQL> r

  1 select a.status astat, b.status bstat, a.name aname, b.name bname

  2 from a left join b

  3 on b.name = a.name

  4 where a.c_id in (

  5 select id from c

  6 where b.name = 'one'

  7 )

  8* and rownum = 1  

     ASTAT      BSTAT ANAME                                    BNAME


---------- ---------- ---------------------------------------- ----------------------------------------
1 4 one one

should be friendlier to the CBO as

SQL> r

  1 with ax as (select a.status, a.name from a

  2 where a.name = 'one'

  3 and a.c_id in (select id from c)

  4 )

  5 select ax.status astat, b.status bstat, ax.name, b.name

  6 from ax, b

  7* where ax.name = b.name  

     ASTAT BSTAT NAME NAME

  • ---------- ---------- ----------

         1 4 one one

         1 2 one one  

SQL> i

  8 and rownum = 1;  

     ASTAT BSTAT NAME NAME

  • ---------- ---------- ----------

         1 4 one one  

SQL> 8   8* and rownum = 1

SQL> c/1/2

  8* and rownum = 2

SQL> r

  1 with ax as (select a.status, a.name from a

  2 where a.name = 'one'

  3 and a.c_id in (select id from c)

  4 )

  5 select ax.status astat, b.status bstat, ax.name, b.name

  6 from ax, b

  7 where ax.name = b.name

  8* and rownum = 2  

no rows selected  

Now if b smaller than a, you can do the similar with statement on b. Since the original is using a b value as a coordinated equality predicate, only the inner join results can be delivered, so if either pruning a or b is expensive compared to joining it with the pruned other, just prune the one cheapest to prune before the join (remembering to restrict the results of to a.id in c if that pruning was skipped as the with clause).  

Now if you really wanted 1,2 instead of 1,4 as the status results, then you need to order the data in the with clause anyway.        

using the data:  

SQL> select * from a;  

        ID NAME STATUS C_ID

  • ---------- ---------- ----------
         1 one                 1         11

         2 two                 1         12

         3 three               1         13

 

SQL> select * from b;  

        ID NAME STATUS

  • ---------- ----------
         1 one                 2

         3 three               2

         1 one                 4

 

SQL> select * from c;  

        ID TYPE

  • ----------------------------------------

        11 type11

        11 type11

        12 type11

        12 type11  

From: oracle-l-bounce_at_freelists.org [mailto:oracle-l-bounce_at_freelists.org] On Behalf Of Krishnaprasad Yadav Sent: Thursday, October 20, 2022 6:55 AM To: Oracle L
Subject: Need help in SQL tunning  

Hi Experts ,  

I have situation , where below was i need to tune , db version :12.1  

SQL Text



select a.status ,
b.status
 from ng_vid_d_verify a left join ng_vid_status b on b.wi_name = a.wi_name
 where a.c_id in (select id
                          from ng_structure_txn 
                           where b.wi_name = :"SYS_B_0"
                           and APPLICANT_TYPE = :"SYS_B_1") 
and rownum =:"SYS_B_2"

<snip>

--

http://www.freelists.org/webpage/oracle-l Received on Sat Oct 22 2022 - 13:38:45 CEST

Original text of this message