Question : Need help with abstract query plan syntax

I'm new to Sybase ASE abstract query plans.  For the code snippet below, don't worry too much about what the query does, but I'm just trying to get a valid syntax for the abstract query plan at the end.  

It just gives me the error:   syntax error; line 1, occurring near 'nl_join'

It looks just like what's in the manuals.  So I'm stumped.

Background:

There is a clustered index named cidx on the #tmp table with all the columns in the order by.  The query (without the query plan qualifier) normally returns rows in the order of the clustered index/order-by *without* doing sorting in a work table, but the user I'm supporting reports occasional problems where the query *does* sort in a tempdb worktable causing all sorts of havoc.

I was trying to add a query plan option to make sure the query didn't use a tempdb worktable

This is probably something really simple, but I can't see it right now.

Thanks
Ben



Code Snippet:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
select top 1 t.f1, t.f2, t.f3, d.f4
from #tmp t, mytable d
where t.f2=d.f2 and t.f3=d.f3
order by t.f5, t.f1, t.f2, t.f3
/* Tell query optimizer to first scan clustered
** index cidx on tmp table #tmp,
** then join the result to the index nc_idx on mytable
*/
plan
"( nl_join ( i_scan cidx table(t #tmp) ) ( i_scan nc_idx table(d mytable) )  )"
Open in New Window Select All

Answer : Need help with abstract query plan syntax

Very interesting question.  You bring up a bunch of issues:

- I suspect by havoc you mean it runs slow and that is what the user is bent out of shape over.

- I am also curious about the fact that it sounds as if your saying that sometimes it avoids the sort and other times it does the worktable sort.  Any idea what the conditions are or what changes occur to cause this behavior to change?  Statistics on #tmp objects (as opposed to "permanent" tempdb.dbo.objects) are notoriously non-existant.  Update stats doesn't take very long unless the #tmp table is really big so you might consider doing that in your code, assuming it is a stored procedure.

- Updating statistics (table and index) on mytable might not be a bad idea either

- Again, assuming all this is in the context of a stored procedure, unless you are creating the #tmp table in a parent proc and querying it in a child procedure, the optimizer is not likely to even find the clustered index.  Even if you force the index with a hint, you will get an information message at runtime stating that the index could not be found so the optimizer is trying something else.

- As it turns out in 12.5.x, you CAN get the optimizer to use an index created in the same procedure IF it is a Primary key.  By changing your Create Cluster Index to Create Constraint Primary Key Cluster, the optimizer does two things.  First, it whines about not being able to find the index and second, it uses the darned thing anyway.  Yea!!!

 - The abstract query plan stuff is not very well documented and the examples are pretty lean.  I have played with it some and had some small successes.  I would not, at this point, attempt to dream up a new query plan from scratch, but that's just me.

- Should we be trying to out-guess the optimizer, not a little bit, but a lot.  We pay for databases because a bunch of smart people have put hundreds of man-years into getting things like the query optimizer to function really well.  ASE 15 is definitely a step up from 12.5.x in this regard.  In addition, you are using a relatively new OLAP feature so it is not too surprising that you are not getting the slickest plan imaginable.

- If we are not getting the performance we need through no fault of the optimizer, should we look at rewriting the query to make it less work to perform.  My vote is to drop back to basics and formulate the query so the optimizer does not have to be omniscient.

Given all of this, my approach would be to rewrite the query so there was no doubt what the most effective path would be.  How about something like...

By dropping the query on #tmp down into a derived table, you probably force that query to complete first.  Of course, it can be satisfied out of the coverage clustered primary key you will have in place.

Again, assuming this is in a stored procedure, you can break it into two pieces and avoid this excercise altogether.

Regards,
Bill
1:
2:
3:
4:
5:
6:
7:
select mT.f1, mT.f2, mT.f3, dT.f4
  from (select top 1 f1, f2, f3
          from #tmp
         order by f5, f1, f2, f3) mT
  join mytable dT
    on dT.f2 = mT.f2
   and dT.f3 = mT.f3
Open in New Window Select All
Random Solutions  
 
programming4us programming4us