The relevant schema for this database is there are Jobs which have Job Phases which have DailyInfos. I wrote a function that takes the DailyInfoID and returns a bunch of data related to that Daily. The idea is that if I want Job Phase To Date values, I would call the function for every DailyInfo in that JobPhase by using cross apply on a query that returns all the DailyInfoIDs for that JobPhase. This works well on the JobPhase level.
Now when I go to the Job level, the query runs MUCH slower. Let's say there are 5 phases in a job, if I run the Job Phase to Date query 5 times for each Job Phase, it runs in a reasonable amount of time. However if I run the first Job To Date query below, it takes MUCH longer. The second version of the query, which uses a table variable instead of a subquery, takes the correct amount of time (ie the sum of the 5 Job Phase To Date queries). Why does the table variable version take so much less time and # rea开发者_如何转开发ds than the subquery version?
Version 1 - Duration: 210,225ms CPU: 206,203ms Reads: 38,737,658
SELECT
di.DailyInfoID,
DailyCycleTimes.NetHaulCY,
DailyCycleTimes.PayCY,
DailyCycleTimes.DigCY,
DailyCycleTimes.FillCY,
DailyCycleTimes.DelayMinutes,
DailyCycleTimes.PumpMinutes,
DailyCycleTimes.TurnMinutes,
DailyCycleTimes.SailToMinutes,
DailyCycleTimes.SailFromMinutes,
DailyCycleTimes.ConnectMinutes,
DailyCycleTimes.DisconnectMinutes,
DailyCycleTimes.DischargeMinutes
FROM
(
SELECT di.DailyInfoID
FROM DailyInfo di
INNER JOIN JobPhase jp ON jp.JobPhaseID = di.JobPhaseID
INNER JOIN Job j ON j.JobID = jp.JobID
WHERE j.JobID = @JobID
)di
CROSS APPLY calc.fGetDailyCycleTimes(di.DailyInfoID) DailyCycleTimes
Version 2 - Duration: 9,654 CPU: 9,593 Reads: 2,039,088
DECLARE @DailyInfo table(DailyInfoID int)
INSERT INTO @DailyInfo
SELECT di.DailyInfoID
FROM DailyInfo di
INNER JOIN JobPhase jp ON jp.JobPhaseID = di.JobPhaseID
INNER JOIN Job j ON j.JobID = jp.JobID
WHERE j.JobID = @JobID
SELECT
di.DailyInfoID,
DailyCycleTimes.NetHaulCY,
DailyCycleTimes.PayCY,
DailyCycleTimes.DigCY,
DailyCycleTimes.FillCY,
DailyCycleTimes.DelayMinutes,
DailyCycleTimes.PumpMinutes,
DailyCycleTimes.TurnMinutes,
DailyCycleTimes.SailToMinutes,
DailyCycleTimes.SailFromMinutes,
DailyCycleTimes.ConnectMinutes,
DailyCycleTimes.DisconnectMinutes,
DailyCycleTimes.DischargeMinutes
FROM @DailyInfo di
CROSS APPLY calc.fGetDailyCycleTimes(di.DailyInfoID) DailyCycleTimes
Check the actual execution plan for each in Management Studio - that will tell you where the cost is attributed for each.
The table variable can't be optimized by the query engine, where the underlying table (when used directly) can.
精彩评论