views:

202

answers:

3

I have a fairly complex (or ugly depending on how you look at it) stored procedure running on SQL Server 2008. It bases a lot of the logic on a view that has a pk table and a fk table. The fk table is left joined to the pk table slightly more than 30 times (the fk table has a poor design - it uses name value pairs that I need to flatten out. Unfortunately, it's 3rd party and I cannot change it).

Anyway, it had been running fine for weeks until I periodically noticed a run that would take 3-5 minutes. It turns out that this is the time it takes to generate the query plan. Once the query plan exists and is cached, the stored procedure itself runs very efficiently. Things run smoothly until there is a reason to regenerate and cache the query plan again.

Has anyone seen this? Why does it take so long to generate the plan? Are there ways to make it come up with a plan faster?

+2  A: 

You can try using a Plan Guide. Plan generation will still last some time, but should be significantly shorter.

Remus Rusanu
+1  A: 

Have you considered rewriting your 30-join SELECT to smth like this?

SELECT [key], NULL AS [a], NULL AS [b]
  INTO #temp
  FROM [pk-table]

UPDATE t SET t.[a] = fk.[a], t.[b] = fk.[b]
  FROM #temp t
  INNER JOIN (
    SELECT f.[key],
      MAX(CASE WHEN f.[name] = 'a' THEN f.[value] ELSE NULL END) AS [a],
      MAX(CASE WHEN f.[name] = 'b' THEN f.[value] ELSE NULL END) AS [b]
    FROM [fk-table] f
    GROUP BY f.[key]
    ) fk ON (fk.[key] = t.[key]

Although it's maybe not an answer to your original question :)

Rad
This is worth a shot too. Though I've tried PIVOT and some CTEs and so far the left joins as a view have been the most efficient. Have you seen this way being faster before?
TheImirOfGroofunkistan
Yes. I had the same logic (multiple (about 20) left-join of "fk-table" to one "master-table"), and execution time dramatically increased after adding another one join of the same table. Rewriting that giant-one-select to two-step-select-update really helped.But maybe it was just a particular case of unfortunate indexes, I didn't go digging.(And sorry, missed "on a view" statement in your post)
Rad
np - the view just makes the reuse of the query simpler, I'm not sure that it's necessary.
TheImirOfGroofunkistan
*Why does it take so long to generate the plan?* Part of it is the number of combination to consider during query optimization. A 30 join select has 30! (30 Factorial) different orders of joins to consider, or about 2.65E32. And order is just one aspect of query optimization to consider. Breaking the query into smaller pieces that store sub-results in temp tables, as Rad suggests, can bring down the optimization work big time, but probably will give a slower plan.
Shannon Severance
I was able to bring the execution plan time down to 3 seconds by removing the joins and making them selects in the select clause of the query.
TheImirOfGroofunkistan
+1  A: 

Something will have caused the plan to require recompiling such as a statistics update or DDL change. The list if here: Execution Plan Caching and Reuse

The query in it's current form will always take 3-5 minutes to recompile: this can't be avoided.

Assuming you can't change it (PIVOT, use a trigger to maintain a "proper" table etc), then you can only control when the recompilation happens.

Remus' plan guide answer is one way. I'd also look at my statistic maintenance and ensure it's done overnight say, so it only happens once at start of day

gbn
Thanks. I'm trying to avoid using the plan guide unless I really have to.Forcing statistics overnight is a good solution. Also, we had thought about trying to use triggers. We don't have a good idea of the actual load on the table yet as it's not a live system yet. But I would like to try it.
TheImirOfGroofunkistan