phosplait (6/16/2015)
So it seems this is definitely an issue of parameter sniffing.While option(recompile) did nothing, option(optimize for unknown) brought the dynamic query down to 3 seconds. Still slower, but I can live with this.
Is there some more correct way to fix this, or would simply leaving that as part of the query be the best solution?
The first posting of the History function looks like this:
CREATE FUNCTION [dbo].[history] (
@First DATE,
@DatedStart DATE = '6/1/2014',
@DatedEnd DATE = NULL,
@Number FLOAT,
@Year INT,
@Sub INT = 5000000
)
...
SELECT DATEADD(day, num - 1, @Sub) AS thedate,
which of course throws an error. I might be wrong, but this suggests that you're in the middle of designing the process, rather than query tuning a process which has been identified as a bottleneck. If this is the case you might want to reconsider the design and configure the inner iTVF as a bogstandard query and reconfigure the outer iTVF as a new function returning a bunch of dates. I'm confident you'd have a far less messy structure to work with. Rejigging your inner iTVF results in something like this:
SELECT
[Year] = YEAR(o.Date),
o.Object,
Amt = SUM(x.ModifiedSize)
FROM [Object] o
INNER JOIN transactions t
ON t.object = o.object
CROSS APPLY (
SELECT ModifiedSize = CASE t.TypeIndicator
WHEN 'P' THEN isnull(Amt, @Substitution) * - 1
WHEN 'S' THEN isnull(Amt, @Substitution)
ELSE 0 END
) x
WHERE o.DatedDate >= @EarliestDated
AND (@LatestDated IS NULL OR o.DatedDate <= @LatestDated)
AND (@Number IS NULL OR o.Number = @Number)
AND (@Year IS NULL OR YEAR(o.Date) = @Year)
AND o.FinalSize IS NOT NULL
AND t.TypeIndicator != 'D'
AND (@OnDate IS NULL OR t.TransDate <= @OnDate)
GROUP BY
YEAR(o.Date),
o.Object
which is simple, easy to adapt, and easy to mark as a problem catch-all query to which the usual caveats and cures apply. The point to remember is this: if you run the process with a single date and then with the widest date range which makes sense with your data, the two execution plans are unlikely to be the same.
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden