RE: A Cure for Madness

  • From: "Anthony Molinaro" <amolinaro@xxxxxxxx>
  • To: <oracle-l@xxxxxxxxxxxxx>
  • Date: Sun, 29 Aug 2004 14:14:27 -0400

Wolfgang,
  I defintely agree with you on some points.
  First, (as Jonathan pointed out to me), Date does mention that
  merging should be allowed, specifically for the sake of performance.
  Second, he goes on to explain that the merging done by the cbo
should/can
  be done as long as it does not cause an error or change the intended
result
  of the query (that's the part I don't like).
  So, I think he's saying (as was Jonathan originally),=20
  sure, go ahead and merge as long as the cbo "knows" what we want to do
and=20
  the merging does not cause an error (even if it's our error).

  In Date's "An Introduction To Database Systems 7th ed.", chapter 17
(Optimization),
  he walks through some simple examples.
  On page 539:
  =20
   ( ( SP JOIN S ) WHERE P# =3D P# ( 'P2' ) ) { SNAME }


  based on the order of how the query was written the cbo would:
   1. join sp and s on p# (getting all the matches!!)
   2. then restrict the P2 tuples
   3. finally project sname

  Date himself (on that same page) suggests the cbo should instead:
   1. restrict sp to only the P2 tuples
   2. join that result to s on p#
   3. finally, project sname

 He gives another example on pg. 545 as well. It's obvious query rewrite
can be beneficial.=20
 He does however state (in the book and article)
 that these optimizations should be done without changing the resultset=20
 ("changing" in regards to the article caused the Invalid Number error).


 My question is, does the merging we notice really change the resultset?
 I don't think so, it barfs because you want to perform a number
comparison on a string.
 Should the cbo have to handle stuff like that???
=20
 If we follow his steps for query optimization, the sql would be
transformed into the relational algebra counterpart.
 He states:
=20
 1.Evaluate R1.=20
 2.Restrict the result of the previous step to just those rows
satisfying NUM > 0.=20
 3.Project the result of the previous step over all of its columns
(which is effectively a no op, of course).=20


 So, for the query in question we have this=20
 (assume the symbol @ =3D=3D restriction and the symbol || =3D=3D =
projection and
* means "all rows" not multiplication)

 R1<-(@where flag=3D'N'(T))
 ||*where num>0(R1)

 If that's the case it sure seems like it is materialized. Let's say for
the sake of argument it is not, though.
 I ask you this, How do you know it's raining outside? You have to go
and look.
 Why does this work SELECT * FROM EMP WHERE ROWNUM=3D1, but this doesn't
SELECT * FROM EMP WHERE ROWNUM=3D2?
 Simple, because you have to go and look at least once. Rownum=3D1 works
because oracle has to try to fetch a row
 to know there are none, or 1, or n. So, my point is, even if the
results are not materialized the cbo
 has to check the condition in the select clause and make sure that it
"makes sense" before merging?
 No, sorry. I have simple examples (9.2.0.4) of the cbo getting
cardinality orders of magnitude wrong
 causing bad plans (optimizer_index_cost_adj wouldn't exist if things
were being done correctly).
 How can you get cardinality wrong? That's so fundemental. Please
Oracle, fix that before
 you add contigency plans in the cbo for poor design. So, bottom line, I
agree, this shouldn't even be an issue.
 It's a design issue.=20

 It will be interesting to see how the sheep factor will kick in here.
 I wonder how many people thought Jonathan's ideas were crazy now think
they are brilliant because Date agrees.

 So, based on Date's writings (article and books), I think the questions
to be debated are:

 1.Should the cbo merge for performance whenever it can?

 OR

 2.Should the cbo be modified to merge only if it does not cause an
error (even if it's our error)?

=20
 - ant
=20
-----Original Message-----
From: Wolfgang Breitling [mailto:breitliw@xxxxxxxxxxxxx]=20
Sent: Sunday, August 29, 2004 12:44 PM
To: oracle-l@xxxxxxxxxxxxx
Subject: Re: A Cure for Madness


It is probably heresy to contradict the great Chris Date, but I disagree

with this part of his follow-up:

"
Now, the SQL standard makes it perfectly clear that the result of the
query

SELECT *
FROM   R1
WHERE  NUM > 0 ;

is defined as follows:

1.      Evaluate R1.
2.      Restrict the result of the previous step to just those rows=20
satisfying NUM > 0.
3.      Project the result of the previous step over all of its columns=20
(which is effectively a no op, of course).

In other words, the inner subquery must be evaluated before the outer
WHERE=20
and SELECT clauses are executed (hence my unequivocal no to the question

"Is this rewriting on the part of the optimizer valid?").  But there's=20
still a little more to be said.  "

Maybe that is the SQL standard, I don't know, I don't have the text of
it,=20
but it is certainly not part of the relational theory whose strength is
the=20
fact that the operations selection (where clause), projection (select=20
clause) and join can be freely interchanged as long as the rules laid
out=20
by the theory are followed. And none of the relational databases
implement=20
Chris' 1-2-3 order of operation. And I am sure everyone would be very
upset=20
if they implemented the rule that a subquery must be evaluated before=20
predicates and selection are applied. Think of the emp table (EMPNO,
ENAME,=20
JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) and create a view that excludes
the=20
sensitive data: emp_vw (select EMPNO, ENAME, JOB, MGR, DEPTNO from emp).

Now, according to Chris' stand, a query like
select * from emp_vw where empno =3D 7369 would not be allowed to apply
the=20
predicate to the underlying emp table but would need to evaluate the
view=20
first ( which consists solely of a select , i.e. a temporary rowsource=20
consisting of the selected columns from the entire emp table has to be=20
built ) before applying the restriction "where empno =3D 7369". Imagine
the=20
performance.

I have said it before and I still content that the original problem is
not=20
caused by the optimizer incorrectly reordering the sequence of
operations=20
but by the fact that the to_number function is not well defined over the

domain (varchar2). If that was not the case we would not have this
debate=20
as the end result would be the same no matter the order of operations.
To=20
prove it I created a function my_to_number which returns a NULL (i.e.=20
undefined) if presented with something that does not represent a number:
create or replace function my_to_number(input in varchar2) return number
is l_num number :=3D NULL; begin
  begin
   l_num :=3D to_number(input);
  exception
   when others then null;
  end;
  return l_num;
end;

SQL> create table subtest (flag varchar2(1), num varchar2(5));
Table created.
SQL> insert into subtest values('N','123');
1 row created.
SQL> insert into subtest values('X','123');
1 row created.
SQL> insert into subtest values('Y','pqr');
1 row created.
SQL> insert into subtest values('N','456');
1 row created.
SQL> insert into subtest values('Z','ijk');
1 row created.
SQL> commit;
Commit complete.
SQL> analyze table subtest compute statistics;
Table analyzed.

Executing the query as is produces the error:
SQL> SELECT SELECT FLAG, NUM
   2  FROM ( SELECT FLAG, TO_NUMBER ( NUM ) NUM
   3         FROM   SUBTEST
   4         WHERE  FLAG =3D 'N' )
   5  WHERE  NUM > 0 ;

ERROR:
ORA-01722: invalid number

Forcing the subquery to be evaluated first gives us the result
SQL> SELECT SELECT FLAG, NUM
   2  FROM ( SELECT rownum, FLAG, TO_NUMBER ( NUM ) NUM
   3         FROM   SUBTEST
   4         WHERE  FLAG =3D 'N' )
   5  WHERE  NUM > 0 ;

F        NUM
- ----------
N        123
N        456
2 rows selected.

Using the extended TO_NUMBER function also gives the same result,
proving=20
that the reordering does not affect the final resultset.
SQL> SELECT SELECT FLAG, NUM
   2  FROM ( SELECT FLAG, my_TO_NUMBER ( NUM ) NUM
   3         FROM   SUBTEST
   4         WHERE  FLAG =3D 'N' )
   5  WHERE  NUM > 0 ;

F        NUM
- ----------
N        123
N        456
2 rows selected.


At 03:19 PM 8/27/2004, you wrote:

>Some of you might have read the article I recently posted on "Subquery=20
>Madness!":
>
>http://five.pairlist.net/pipermail/oracle-article/2004/000012.html
>
>Chris Date took an interest in the issue, and he wrote a fascinating=20
>follow-up, "A Cure for Madness," which just went live today:
>
>http://www.dbdebunk.com/page/page/1351381.htm
>
>Please note that Chris is *not* saying that the subquery results need=20
>to be materialized, but only that the final results need to be "as if"=20
>they had been. I can think of at least two ways to merge the subquery=20
>and yet maintain the required "as if" behavior.
>
>Chris's article is really clear and well-written. I wish I could write=20
>as well as he does. I think you'll find his article interesting no=20
>matter which side of the issue you personally fall on.

Regards

Wolfgang Breitling
Centrex Consulting Corporation
www.centrexcc.com=20

----------------------------------------------------------------
Please see the official ORACLE-L FAQ: http://www.orafaq.com
----------------------------------------------------------------
To unsubscribe send email to:  oracle-l-request@xxxxxxxxxxxxx put
'unsubscribe' in the subject line.
--
Archives are at //www.freelists.org/archives/oracle-l/
FAQ is at //www.freelists.org/help/fom-serve/cache/1.html
-----------------------------------------------------------------
----------------------------------------------------------------
Please see the official ORACLE-L FAQ: http://www.orafaq.com
----------------------------------------------------------------
To unsubscribe send email to:  oracle-l-request@xxxxxxxxxxxxx
put 'unsubscribe' in the subject line.
--
Archives are at //www.freelists.org/archives/oracle-l/
FAQ is at //www.freelists.org/help/fom-serve/cache/1.html
-----------------------------------------------------------------

Other related posts: