views:

33

answers:

1

I have a complex view that I use to pull a list of primary keys that indicate rows in a table that have been modified between two temporal points.

This view has to query 13 related tables and look at a changelog table to determine if a entity is "dirty" or not.

Even with all of this going on, doing a simple query:

select * from vwDirtyEntities;

Takes only 2 seconds.

However, if I change it to

select
    e.Name
from 
    Entities e 
         inner join vwDirtyEntities de
             on e.Entity_ID = de.Entity_ID

This takes 1.5 minutes.

However, if I do this:

declare @dirtyEntities table
(
    Entity_id uniqueidentifier;
)

insert into @dirtyEntities 
   select * from vwDirtyEntities;


select
   e.Name
from 
    Entities e 
        inner join @dirtyEntities de
           on e.Entity_ID = de.Entity_ID

I get the same results in only 2 seconds.

This leads me to believe that SQLServer is evaluating the view per row when joined to Entities, instead of constructing a query plan that involves joining the single inner join above to the other joins in the view.

Note that I want to join against the full result set from this view, as it filters out only the keys I want internally.

I know I could make it into a materialized view, but this would involve schema binding the view and it's dependencies and I don't like the overhead maintaining the index would cause (This view is only queried for exports, while there are far more writes to the underlying tables).

So, aside from using a table variable to cache the view results, is there any way to tell SQL Server to cache the view while evaluating the join? I tried changing the join order (Select from the view and join against Entities), however that did not make any difference.

The view itself is also very efficient, and there is no room to optimize there.

EDIT: Perhaps this is a question that is better answered on a more dedicated database forum, since I've noticed that questions of this nature tend to languish on StackOverflow, so I'd also welcome any suggestions for alternative sites to pose this question.

+3  A: 

There is nothing magical about a view. It's a macro that expands. The optimiser decides when JOINed to expand the view into the main query.

I'll address other points in your post:

  • you have ruled out an indexed view. A view can only be a discrete entity when it is indexed

  • SQL Server will never do a RBAR query on it's own. Only developers can write loops.

  • there is no concept of caching: every query uses latest data unless you use temp tables

  • you insist on using the view which you've decided is very efficient. But have no idea how views are treated by the optimizer and it has 13 tables

  • SQL is declarative: join order usually does not matter

  • Many serious DB developer don't use views because of limitations like this: they are not reusable because they are macros

Note:

Don't even consider editing or replying with the same tone you used for OMG Ponies. And if you post on a serious DB forum then consider that someone like he or I could be a moderator...

Edit, another possibility. Predicate pushing on SQL Server 2005. That is, SQL Server can not push the JOIN condition "deeper" into the view.

gbn
If you look at the post edit history for Omg Ponies, you'll see that I replied with a simple comment (still there), and he went unhinged. For context, here is his original answer: http://stackoverflow.com/revisions/2be5678d-7d09-4c14-9043-c4769f9f9c03/view-source.
FlySwat
And here is the edit he did after my comment: http://stackoverflow.com/revisions/0d5a1cb1-1f89-4fba-96f4-c270d0543805/view-source . I never attacked him, he started flipping out.
FlySwat
In regards to join order not mattering. That may be true in theory, but in practice I've seen explicitly re-ordering joins to be beneficial, usually because it allows the database to discard larger sets of data that will not match before evaluating other joins.
FlySwat
Also, I'm fully aware that a view is a macro. However, what I don't understand is why the non macro version (not shown in my question) far outperforms the view version. Obviously views are more than macros in the case of SQLServer.
FlySwat
Btw, I voted your answer up because you have provided a helpful response and read my question fully before answering.
FlySwat
1. A view *is*a macro, no more, no less. Unless indexed. SQL Server is ignoring the view because it does not exists and uses the base table.
gbn
Perhaps the issue is that the way I wrote the non view one is more efficient than how SQL Server is expanding the view. Perhaps it is making the view into a correlated subquery.
FlySwat
2. JOIN order really only matters for complex queries when the cost of working out the best plan is too high. In this case, it's either not complex enough for this to happen, or SQL Server decides on the same plan anyway.
gbn
3. See update. Depends on version. It won't be correlated because there is no reason unless subquery or EXISTS is used (usually).
gbn
That is a good point and I am using 2005. I'll investigate that. Thank you.
FlySwat