RE: improve cardinality estimation

  • From: "Mark W. Farnham" <mwf@xxxxxxxx>
  • To: <jlewisoracle@xxxxxxxxx>, <laurentiu.oprea06@xxxxxxxxx>
  • Date: Tue, 27 Oct 2020 15:22:50 -0400

Your re-write is indeed correct now, Laurentiu’s that I also mistook as correct 
was wrong. I missed that it would include any future “from_dates” based on my 
earlier misreading that it was the same column. Sigh.

 

But Laurentiu can’t change the code at all, so I am still stuck on how to make 
the CBO get it without actually changing the nulls to “tomorrow” every day. 
That might also speed up a lot of their stuff as long as it doesn’t break 
anything. I’m not even sure that fixes it with the function reference on top of 
it, so Laurentiu might end up with the 5% guess anyway.

 

I suppose Laurentiu could slap in a huge number of additional rows (to make up 
the 95%) and give them a future from_date, so the 5% guess turns out to be 
accurate. Sigh. Before you would do that you would punch the stats to a lie, 
right? Run a count(*) and multiply by 20, put that in the relevant stats? Maybe 
this doesn’t change in number very often. Just lie about the stats, and if all 
the code has this awkward “null means not ended yet” translation that should 
work out okay.

 

Anything I can think of leaves out the indeterminate future col_to_date 
represented by null. Someone, somewhere, decided that from start until null end 
date and then eventually updating the end date was less update work than 
current_flag=’Y’ until current_flag is toggled to null. Or a to date using high 
values for the date being updated to a real date, which does take some storage, 
but this is tiny. But we can’t change the code, so we would still get that 5% 
function estimate, right?

 

We can’t reference sysdate in the creation of a virtual column, and this is way 
too small to use your virtual column partitioning trick to a  productive result.

 

mwf

 

From: oracle-l-bounce@xxxxxxxxxxxxx [mailto:oracle-l-bounce@xxxxxxxxxxxxx] On ;
Behalf Of Jonathan Lewis
Sent: Tuesday, October 27, 2020 2:27 PM
To: laurentiu.oprea06@xxxxxxxxx
Cc: ORACLE-L (oracle-l@xxxxxxxxxxxxx)
Subject: Re: improve cardinality estimation

 

 

Was there a version somewhere ?

12c is better than 11g since virtual columns can then be declared invisible, 
but for 11g: 

 

alter table XXX add from_virtual generated always as (trunc(col_from_date)) 
virtual;
alter table XXX add to_virtual generated always as (trunc(col_to_date)) virtual;
execute dbms_stats.gather_table_stats(user,'XXX');

 

Very important to gather the stats so Oracle doesn't have to use the 5% guess 
etc. for "function of column".

 

 

select count(*) from XXX where

where
        sysdate >= trunc(col_from_date)
and     (sysdate <= trunc(col_to_date)
         or trunc(col_to_date) is null
        )
/

 

Regards

Jonathan Lewis

 

 

On Tue, 27 Oct 2020 at 15:32, Laurentiu Oprea <laurentiu.oprea06@xxxxxxxxx> 
wrote:

Hello,

 

I found a query with a very bad execution plan due to low cardinality 
evaluation of below where clause

 

where

sysdate between trunc(col_from_date) and trunc(nvl(col_to_date,sysdate+1))

 

Is there any way I can improve the estimate (like extended stats, etc) ?

 

Thanks for your help.

Other related posts: