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