You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by Manjula Kutty <ma...@gmail.com> on 2008/10/01 23:26:42 UTC

Question regarding runtimestatistics and join order

Hi

I'm trying to convert subquery.sql to junit and found this comment on the
original test :

-- DERBY-1007: Optimizer for subqueries can return incorrect cost estimates
-- leading to sub-optimal join orders for the outer query.  Before the patch
-- for that isssue, the following query plan will show T3 first and then
T1--
-- but that's determined by the optimizer to be the "bad" join order.  After
-- the fix, the join order will show T1 first, then T3, which is correct
-- (based on the optimizer's estimates).
And I ran the values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
And the plan returned was

Statement Name:
   null
Statement Text:
    select x1.j, x2.b from (select distinct i,j from t1) x1, (select
distinct a,b from t3) x2 where x1.i = x2.a order by x1.j, x2.b
Parse Time: 0
Bind Time: 0
Optimize Time: 0
Generate Time: 0
Compile Time: 0
Execute Time: 0
Begin Compilation Timestamp : null
End Compilation Timestamp : null
Begin Execution Timestamp : null
End Execution Timestamp : null
Statement Execution Plan Text:
Sort ResultSet:
Number of opens = 1
Rows input = 4
Rows returned = 4
Eliminate duplicates = false
In sorted order = false
Sort information:
   Number of rows input=4
   Number of rows output=4
   Sort type=internal
   constructor time (milliseconds) = 0
   open time (milliseconds) = 0
   next time (milliseconds) = 0
   close time (milliseconds) = 0
   optimizer estimated row count:          130.00
   optimizer estimated cost:          330.98
Source result set:
   Project-Restrict ResultSet (5):
   Number of opens = 1
   Rows seen = 4
   Rows filtered = 0
   restriction = false
   projection = true
       constructor time (milliseconds) = 0
       open time (milliseconds) = 0
       next time (milliseconds) = 0
       close time (milliseconds) = 0
       restriction time (milliseconds) = 0
       projection time (milliseconds) = 0
       optimizer estimated row count:          130.00
       optimizer estimated cost:          330.98
   Source result set:
       Hash Join ResultSet:
       Number of opens = 1
       Rows seen from the left = 5
       Rows seen from the right = 4
       Rows filtered = 0
       Rows returned = 4
           constructor time (milliseconds) = 0
           open time (milliseconds) = 0
           next time (milliseconds) = 0
           close time (milliseconds) = 0
           optimizer estimated row count:          130.00
           optimizer estimated cost:          330.98
       Left result set:
           Distinct Scan ResultSet for T1 at read committed isolation level
using instantaneous share row locking:
           Number of opens = 1
           Hash table size = 5
           Distinct columns are column numbers (0,1)
           Rows seen = 5
           Rows filtered = 0
               constructor time (milliseconds) = 0
               open time (milliseconds) = 0
               next time (milliseconds) = 0
               close time (milliseconds) = 0
               optimizer estimated row count:           10.00
               optimizer estimated cost:           35.34
               next time in milliseconds/row = 0
           scan information:
               Bit set of columns fetched=All
               Number of columns fetched=2
               Number of pages visited=1
               Number of rows qualified=5
               Number of rows visited=5
               Scan type=heap
               start position:
null               stop position:
null               scan qualifiers:
None
               next qualifiers:
None
               optimizer estimated row count:           10.00
               optimizer estimated cost:           35.34
       Right result set:
           Hash Table ResultSet (4):
           Number of opens = 5
           Hash table size = 9
           Hash key is column number 0
           Rows seen = 9
           Rows filtered = 0
               constructor time (milliseconds) = 0
               open time (milliseconds) = 0
               next time (milliseconds) = 0
               close time (milliseconds) = 0
               optimizer estimated row count:           13.00
               optimizer estimated cost:          295.64
               next time in milliseconds/row = 0
               next qualifiers:
Column[0][0] Id: 0
Operator: =
Ordered nulls: false
Unknown return value: false
Negate comparison result: false
           Source result set:
               Distinct Scan ResultSet for T3 at read committed isolation
level using instantaneous share row locking:
               Number of opens = 1
               Hash table size = 9
               Distinct columns are column numbers (0,1)
               Rows seen = 9
               Rows filtered = 0
                   constructor time (milliseconds) = 0
                   open time (milliseconds) = 0
                   next time (milliseconds) = 0
                   close time (milliseconds) = 0
                   optimizer estimated row count:           13.00
                   optimizer estimated cost:          295.64
                   next time in milliseconds/row = 0
               scan information:
                   Bit set of columns fetched=All
                   Number of columns fetched=2
                   Number of pages visited=1
                   Number of rows qualified=9
                   Number of rows visited=9
                   Scan type=heap
                   start position:
null                   stop position:
null                   scan qualifiers:
None
                   next qualifiers:
None
                   optimizer estimated row count:           13.00
                   optimizer estimated cost:          295.64


My question is how do I find the join order from this plan? How should I do
an assert statement with this plan??

Thanks in advance for your help

Manjula

-- 
Thanks,
Manjula.

Re: Question regarding runtimestatistics and join order

Posted by Army <qo...@gmail.com>.
Kathey Marsden wrote:
>
> As for how to incorporate this into RuntimeStatisticsParser, the only 
> thing I can think of is to add an boolean orderedSearchStrings(String[] 
> searchStrings) method to RuntimeStatistics parser that will search for 
> the specified strings in order and return true if they are there in the 
> order they are in the array.

I think this works so long as:

   1) the table names in the query do not appear elsewhere in the query 
plan (ex. a table name of "T" would match the first letter of the word 
"Table" in "Hash Table ResultSet", which we wouldn't want), and

   2) the argument array passed to the new function includes *ALL* 
tables in the query, not just a subset.

With respect to #2, if my query is of the form:

   select ... from
     (select ... from t2, t1, t3 where ...) X1
     (select ... from t1, t2 where ...) X2
   where ...

Assume a test wants to verify that the tables in subquery X2 have a join 
order of { T2, T1 }, but doesn't really care about the join order of the 
subquery in X1, nor does it care about the order of X1 w.r.t. X2.  You'd 
*still* have to make sure that the array passed into the ordered search 
method includes the join order for X1, as well, otherwise the test might 
incorrectly pass.

For example, if we only check for the join order of the "targeted" 
subquery X2, meaning we pass ["T2", "T1"] into the proposed method and 
ignore X1 altogether, then the test would IN-correctly PASS for the 
following query plan:

   ProjectRestrict:
   +++ JoinNode_0:
   ++++++ LeftResultSet:                  <== This corresponds to X1
   +++++++++ JoinNode_1:
   ++++++++++++ LeftResultSet:
   +++++++++++++++ JoinNode_2:
   ++++++++++++++++++ LeftResultSet: T3
   ++++++++++++++++++ RightResultSet: T2
   ++++++++++++ RightResultSet: T1
   ++++++ RightResultSet:                 <== This corresponds to X2
   +++++++++ JoinNode_3:
   ++++++++++++ LeftResultSet: T1
   ++++++++++++ RightResultSet: T2


If you just search for "T1" followed by "T2", the test will pass because 
the join order for X1 matches--but that's wrong because it's really X2 
that we wanted to check.

If instead of ["T1", "T2"] you pass in ["T3", "T2", "T1", "T2", 
"T1"]--i.e. include *ALL* tables in the query, even the ones that aren't 
necessarily targeted--then I think you'd get the desired behavior. The 
downside to this is that the test will fail if a join order about which 
we "don't care" changes (ex. the join order for X1 in this case).  But 
that's how things work today with the canon-based test, as well, so even 
if it's not ideal, at least it wouldn't really be any worse...

To get the ideal behavior (where the test fails if and only if the 
"targeted" subquery's join order is not what is expected) with the 
proposed orderedSearchStrings() approach, one would have to ensure that 
the table names used in the targeted subquery do not appear anywhere 
else in the query.  My guess is that you would have to rewrite a good 
number of tests to guarantee that, which would probably be non-trivial.

So it seems like the easiest approach would be to follow Kathey's 
suggestion, but make sure that all tests which use the new method pass 
in a full list of all base table names in the query (not just a targeted 
subset).

Army


Re: Question regarding runtimestatistics and join order

Posted by Knut Anders Hatlen <Kn...@Sun.COM>.
Kathey Marsden <km...@sbcglobal.net> writes:

> Army wrote:
>>
>> As a general rule, when looking at a given query plan the join order
>> is reflected by the order in which you see the table names as you
>> scroll from the top of the plan downward.
>>
> As for how to incorporate this into RuntimeStatisticsParser, the only
> thing I can think of is to add an boolean
> orderedSearchStrings(String[] searchStrings) method to
> RuntimeStatistics parser that will search for the specified strings in
> order and return true if they are there in the order they are in the
> array.

Or change the runtime statistics output to something that's easier to
parse. Sexp or XML or something... :)

-- 
Knut Anders

Re: Question regarding runtimestatistics and join order

Posted by Manjula Kutty <ma...@gmail.com>.
Thank you Knut and Army  for the detailed explanation. Again now I have the
same question that Kathey raised...

Thanks
Manjula

On Thu, Oct 2, 2008 at 9:25 AM, Kathey Marsden
<km...@sbcglobal.net>wrote:

> Army wrote:
>
>>
>> As a general rule, when looking at a given query plan the join order is
>> reflected by the order in which you see the table names as you scroll from
>> the top of the plan downward.
>>
>> As for how to incorporate this into RuntimeStatisticsParser, the only
> thing I can think of is to add an boolean orderedSearchStrings(String[]
> searchStrings) method to RuntimeStatistics parser that will search for the
> specified strings in order and return true if they are there in the order
> they are in the array.
>
>
> Kathey
>
>
>


-- 
Thanks,
Manjula.

Re: Question regarding runtimestatistics and join order

Posted by Kathey Marsden <km...@sbcglobal.net>.
Army wrote:
>
> As a general rule, when looking at a given query plan the join order 
> is reflected by the order in which you see the table names as you 
> scroll from the top of the plan downward.
>
As for how to incorporate this into RuntimeStatisticsParser, the only 
thing I can think of is to add an boolean orderedSearchStrings(String[] 
searchStrings) method to RuntimeStatistics parser that will search for 
the specified strings in order and return true if they are there in the 
order they are in the array.


Kathey



Re: Question regarding runtimestatistics and join order

Posted by Army <qo...@gmail.com>.
Knut Anders Hatlen wrote:
> Manjula Kutty <ma...@gmail.com> writes:
>> In the given plan did you find anything about the join order??
> 
> I think the join order is T1, T3. Under Hash Join ResultSet, the plan
> says that the left result set is a Distinct Scan ResultSet for T1, and
> the right result set is a Hash Table ResultSet whose source result set
> is a Distinct Scan ResultSet for T3.

Right.

As a general rule, when looking at a given query plan the join order is 
reflected by the order in which you see the table names as you scroll 
from the top of the plan downward.

In the plan that Manjula originally posted "T1" appears first (i.e. 
closer to the beginning of the plan), then "T3" appears afterward, so 
that's a general indication that the join order is "T1", "T3".

Note that with respect to the top-level query in question, i.e. to:

   select x1.j, x2.b from
     (select distinct i,j from t1) x1,
     (select  distinct a,b from t3) x2
   where x1.i = x2.a
   order by x1.j, x2.b

the join order is _technically_ { X1, X2 }.  But the query plan only 
shows base table access, so we have to look to see what tables X1 and X2 
access.  In this case X1 accesses T1 while X2 accesses T3, so when we 
scan the plan and see { T1, T3 }, that effectively implies a join order 
of { X1, X2 }.  I'm not sure if the test comments are consistent in 
terms of whether they'll say { T1, T3 } or { X1, X2 }, so I thought I'd 
mention it...

On a more general level, the "scan downward" approach to finding the 
join order works because the query plan is written in terms of "left" 
and "right" result sets, as Knut Anders mentioned.  If I'm joining three 
tables T1, T2, T3 and the join order chosen by the optimizer is {T2, T3, 
T1} the final query tree will look something like:

        JOIN_0
         /  \
     JOIN_1  T1
       /  \
      T2   T3

Notice how each join node has a "left" and a "right" child.  The query 
plan is generated in depth-first traversal order (starting with the 
root), so the query plan for the above tree would look something like:

JoinResultSet_0:
+++ LeftResultSet:
++++++ JoinResultSet_1:
+++++++++ LeftResultSet:  T2
+++++++++ RightResultSet: T3
+++ RightResultSet:       T1

 From this we can see that the order in which the tables appear in the 
query plan (reading top to bottom) will match the order that comes from 
reading the leaf nodes of the join tree left-to-right, and that in turn 
reflects the join order chosen by the optimizer.

Army


Re: Question regarding runtimestatistics and join order

Posted by Knut Anders Hatlen <Kn...@Sun.COM>.
Manjula Kutty <ma...@gmail.com> writes:

> Thanks for the reply Mamta. But the thing is I could not find the
> specic join order in the runstime statistics plan. May be I don't know
> how ot read it? In the given plan did you find anything about the join
> order??

Hi Manjula,

I think the join order is T1, T3. Under Hash Join ResultSet, the plan
says that the left result set is a Distinct Scan ResultSet for T1, and
the right result set is a Hash Table ResultSet whose source result set
is a Distinct Scan ResultSet for T3.

-- 
Knut Anders

Re: Question regarding runtimestatistics and join order

Posted by Manjula Kutty <ma...@gmail.com>.
Thanks for the reply Mamta. But the thing is I could not find the specic
join order in the runstime statistics plan. May be I don't know how ot read
it? In the given plan did you find anything about the join order??

On Wed, Oct 1, 2008 at 4:51 PM, Mamta Satoor <ms...@gmail.com> wrote:

> Manjula, there are some existing utility methods in
> RuntimeStatisticsParser which may help you determine if your query is
> using the right join order or not. If not, I wonder if a new method
> can be written to provide that functionality. I just copied some
> sample code about how we enforce that the expected index was used for
> a given query. This is from the junit test
> lang/UpdateStatisticsTest.java
>              JDBC.assertDrainResults(ps.executeQuery());
>               RuntimeStatisticsParser rtsp =
> SQLUtilities.getRuntimeStatisticsParser(s);
>               assertTrue(rtsp.usedSpecificIndexForIndexScan("T2","T2I1"));
>
> Mamta
>
> On Wed, Oct 1, 2008 at 2:26 PM, Manjula Kutty <ma...@gmail.com>
> wrote:
> > Hi
> >
> > I'm trying to convert subquery.sql to junit and found this comment on the
> > original test :
> >
> > -- DERBY-1007: Optimizer for subqueries can return incorrect cost
> estimates
> > -- leading to sub-optimal join orders for the outer query.  Before the
> patch
> > -- for that isssue, the following query plan will show T3 first and then
> > T1--
> > -- but that's determined by the optimizer to be the "bad" join order.
>  After
> > -- the fix, the join order will show T1 first, then T3, which is correct
> > -- (based on the optimizer's estimates).
> > And I ran the values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
> > And the plan returned was
> >
> > Statement Name:
> >    null
> > Statement Text:
> >     select x1.j, x2.b from (select distinct i,j from t1) x1, (select
> > distinct a,b from t3) x2 where x1.i = x2.a order by x1.j, x2.b
> > Parse Time: 0
> > Bind Time: 0
> > Optimize Time: 0
> > Generate Time: 0
> > Compile Time: 0
> > Execute Time: 0
> > Begin Compilation Timestamp : null
> > End Compilation Timestamp : null
> > Begin Execution Timestamp : null
> > End Execution Timestamp : null
> > Statement Execution Plan Text:
> > Sort ResultSet:
> > Number of opens = 1
> > Rows input = 4
> > Rows returned = 4
> > Eliminate duplicates = false
> > In sorted order = false
> > Sort information:
> >    Number of rows input=4
> >    Number of rows output=4
> >    Sort type=internal
> >    constructor time (milliseconds) = 0
> >    open time (milliseconds) = 0
> >    next time (milliseconds) = 0
> >    close time (milliseconds) = 0
> >    optimizer estimated row count:          130.00
> >    optimizer estimated cost:          330.98
> > Source result set:
> >    Project-Restrict ResultSet (5):
> >    Number of opens = 1
> >    Rows seen = 4
> >    Rows filtered = 0
> >    restriction = false
> >    projection = true
> >        constructor time (milliseconds) = 0
> >        open time (milliseconds) = 0
> >        next time (milliseconds) = 0
> >        close time (milliseconds) = 0
> >        restriction time (milliseconds) = 0
> >        projection time (milliseconds) = 0
> >        optimizer estimated row count:          130.00
> >        optimizer estimated cost:          330.98
> >    Source result set:
> >        Hash Join ResultSet:
> >        Number of opens = 1
> >        Rows seen from the left = 5
> >        Rows seen from the right = 4
> >        Rows filtered = 0
> >        Rows returned = 4
> >            constructor time (milliseconds) = 0
> >            open time (milliseconds) = 0
> >            next time (milliseconds) = 0
> >            close time (milliseconds) = 0
> >            optimizer estimated row count:          130.00
> >            optimizer estimated cost:          330.98
> >        Left result set:
> >            Distinct Scan ResultSet for T1 at read committed isolation
> level
> > using instantaneous share row locking:
> >            Number of opens = 1
> >            Hash table size = 5
> >            Distinct columns are column numbers (0,1)
> >            Rows seen = 5
> >            Rows filtered = 0
> >                constructor time (milliseconds) = 0
> >                open time (milliseconds) = 0
> >                next time (milliseconds) = 0
> >                close time (milliseconds) = 0
> >                optimizer estimated row count:           10.00
> >                optimizer estimated cost:           35.34
> >                next time in milliseconds/row = 0
> >            scan information:
> >                Bit set of columns fetched=All
> >                Number of columns fetched=2
> >                Number of pages visited=1
> >                Number of rows qualified=5
> >                Number of rows visited=5
> >                Scan type=heap
> >                start position:
> > null               stop position:
> > null               scan qualifiers:
> > None
> >                next qualifiers:
> > None
> >                optimizer estimated row count:           10.00
> >                optimizer estimated cost:           35.34
> >        Right result set:
> >            Hash Table ResultSet (4):
> >            Number of opens = 5
> >            Hash table size = 9
> >            Hash key is column number 0
> >            Rows seen = 9
> >            Rows filtered = 0
> >                constructor time (milliseconds) = 0
> >                open time (milliseconds) = 0
> >                next time (milliseconds) = 0
> >                close time (milliseconds) = 0
> >                optimizer estimated row count:           13.00
> >                optimizer estimated cost:          295.64
> >                next time in milliseconds/row = 0
> >                next qualifiers:
> > Column[0][0] Id: 0
> > Operator: =
> > Ordered nulls: false
> > Unknown return value: false
> > Negate comparison result: false
> >            Source result set:
> >                Distinct Scan ResultSet for T3 at read committed isolation
> > level using instantaneous share row locking:
> >                Number of opens = 1
> >                Hash table size = 9
> >                Distinct columns are column numbers (0,1)
> >                Rows seen = 9
> >                Rows filtered = 0
> >                    constructor time (milliseconds) = 0
> >                    open time (milliseconds) = 0
> >                    next time (milliseconds) = 0
> >                    close time (milliseconds) = 0
> >                    optimizer estimated row count:           13.00
> >                    optimizer estimated cost:          295.64
> >                    next time in milliseconds/row = 0
> >                scan information:
> >                    Bit set of columns fetched=All
> >                    Number of columns fetched=2
> >                    Number of pages visited=1
> >                    Number of rows qualified=9
> >                    Number of rows visited=9
> >                    Scan type=heap
> >                    start position:
> > null                   stop position:
> > null                   scan qualifiers:
> > None
> >                    next qualifiers:
> > None
> >                    optimizer estimated row count:           13.00
> >                    optimizer estimated cost:          295.64
> >
> >
> > My question is how do I find the join order from this plan? How should I
> do
> > an assert statement with this plan??
> >
> > Thanks in advance for your help
> >
> > Manjula
> >
> > --
> > Thanks,
> > Manjula.
> >
>



-- 
Thanks,
Manjula.

Re: Question regarding runtimestatistics and join order

Posted by Mamta Satoor <ms...@gmail.com>.
Manjula, there are some existing utility methods in
RuntimeStatisticsParser which may help you determine if your query is
using the right join order or not. If not, I wonder if a new method
can be written to provide that functionality. I just copied some
sample code about how we enforce that the expected index was used for
a given query. This is from the junit test
lang/UpdateStatisticsTest.java
              JDBC.assertDrainResults(ps.executeQuery());
               RuntimeStatisticsParser rtsp =
SQLUtilities.getRuntimeStatisticsParser(s);
               assertTrue(rtsp.usedSpecificIndexForIndexScan("T2","T2I1"));

Mamta

On Wed, Oct 1, 2008 at 2:26 PM, Manjula Kutty <ma...@gmail.com> wrote:
> Hi
>
> I'm trying to convert subquery.sql to junit and found this comment on the
> original test :
>
> -- DERBY-1007: Optimizer for subqueries can return incorrect cost estimates
> -- leading to sub-optimal join orders for the outer query.  Before the patch
> -- for that isssue, the following query plan will show T3 first and then
> T1--
> -- but that's determined by the optimizer to be the "bad" join order.  After
> -- the fix, the join order will show T1 first, then T3, which is correct
> -- (based on the optimizer's estimates).
> And I ran the values SYSCS_UTIL.SYSCS_GET_RUNTIMESTATISTICS();
> And the plan returned was
>
> Statement Name:
>    null
> Statement Text:
>     select x1.j, x2.b from (select distinct i,j from t1) x1, (select
> distinct a,b from t3) x2 where x1.i = x2.a order by x1.j, x2.b
> Parse Time: 0
> Bind Time: 0
> Optimize Time: 0
> Generate Time: 0
> Compile Time: 0
> Execute Time: 0
> Begin Compilation Timestamp : null
> End Compilation Timestamp : null
> Begin Execution Timestamp : null
> End Execution Timestamp : null
> Statement Execution Plan Text:
> Sort ResultSet:
> Number of opens = 1
> Rows input = 4
> Rows returned = 4
> Eliminate duplicates = false
> In sorted order = false
> Sort information:
>    Number of rows input=4
>    Number of rows output=4
>    Sort type=internal
>    constructor time (milliseconds) = 0
>    open time (milliseconds) = 0
>    next time (milliseconds) = 0
>    close time (milliseconds) = 0
>    optimizer estimated row count:          130.00
>    optimizer estimated cost:          330.98
> Source result set:
>    Project-Restrict ResultSet (5):
>    Number of opens = 1
>    Rows seen = 4
>    Rows filtered = 0
>    restriction = false
>    projection = true
>        constructor time (milliseconds) = 0
>        open time (milliseconds) = 0
>        next time (milliseconds) = 0
>        close time (milliseconds) = 0
>        restriction time (milliseconds) = 0
>        projection time (milliseconds) = 0
>        optimizer estimated row count:          130.00
>        optimizer estimated cost:          330.98
>    Source result set:
>        Hash Join ResultSet:
>        Number of opens = 1
>        Rows seen from the left = 5
>        Rows seen from the right = 4
>        Rows filtered = 0
>        Rows returned = 4
>            constructor time (milliseconds) = 0
>            open time (milliseconds) = 0
>            next time (milliseconds) = 0
>            close time (milliseconds) = 0
>            optimizer estimated row count:          130.00
>            optimizer estimated cost:          330.98
>        Left result set:
>            Distinct Scan ResultSet for T1 at read committed isolation level
> using instantaneous share row locking:
>            Number of opens = 1
>            Hash table size = 5
>            Distinct columns are column numbers (0,1)
>            Rows seen = 5
>            Rows filtered = 0
>                constructor time (milliseconds) = 0
>                open time (milliseconds) = 0
>                next time (milliseconds) = 0
>                close time (milliseconds) = 0
>                optimizer estimated row count:           10.00
>                optimizer estimated cost:           35.34
>                next time in milliseconds/row = 0
>            scan information:
>                Bit set of columns fetched=All
>                Number of columns fetched=2
>                Number of pages visited=1
>                Number of rows qualified=5
>                Number of rows visited=5
>                Scan type=heap
>                start position:
> null               stop position:
> null               scan qualifiers:
> None
>                next qualifiers:
> None
>                optimizer estimated row count:           10.00
>                optimizer estimated cost:           35.34
>        Right result set:
>            Hash Table ResultSet (4):
>            Number of opens = 5
>            Hash table size = 9
>            Hash key is column number 0
>            Rows seen = 9
>            Rows filtered = 0
>                constructor time (milliseconds) = 0
>                open time (milliseconds) = 0
>                next time (milliseconds) = 0
>                close time (milliseconds) = 0
>                optimizer estimated row count:           13.00
>                optimizer estimated cost:          295.64
>                next time in milliseconds/row = 0
>                next qualifiers:
> Column[0][0] Id: 0
> Operator: =
> Ordered nulls: false
> Unknown return value: false
> Negate comparison result: false
>            Source result set:
>                Distinct Scan ResultSet for T3 at read committed isolation
> level using instantaneous share row locking:
>                Number of opens = 1
>                Hash table size = 9
>                Distinct columns are column numbers (0,1)
>                Rows seen = 9
>                Rows filtered = 0
>                    constructor time (milliseconds) = 0
>                    open time (milliseconds) = 0
>                    next time (milliseconds) = 0
>                    close time (milliseconds) = 0
>                    optimizer estimated row count:           13.00
>                    optimizer estimated cost:          295.64
>                    next time in milliseconds/row = 0
>                scan information:
>                    Bit set of columns fetched=All
>                    Number of columns fetched=2
>                    Number of pages visited=1
>                    Number of rows qualified=9
>                    Number of rows visited=9
>                    Scan type=heap
>                    start position:
> null                   stop position:
> null                   scan qualifiers:
> None
>                    next qualifiers:
> None
>                    optimizer estimated row count:           13.00
>                    optimizer estimated cost:          295.64
>
>
> My question is how do I find the join order from this plan? How should I do
> an assert statement with this plan??
>
> Thanks in advance for your help
>
> Manjula
>
> --
> Thanks,
> Manjula.
>