Le schéma pertinent pour cette base de données est qu'il existe des Jobs ayant des Phases de Job ayant DailyInfos. J'ai écrit une fonction qui prend le DailyInfoID et retourne un tas de données liées à ce Daily. L'idée est que si je veux des valeurs Job Phase To Date, j'appellerais la fonction pour chaque DailyInfo dans cette JobPhase en utilisant cross apply sur une requête qui retourne tous les DailyInfoID pour cette JobPhase. Cela fonctionne bien au niveau JobPhase.T-SQL 2 versions de la même requête: Pourquoi l'une s'exécute en 10 secondes, l'autre en 206 secondes (variable table vs sous-requête)
Maintenant, quand je vais au niveau du travail, la requête s'exécute beaucoup plus lentement. Disons qu'il y a 5 phases dans un travail, si j'exécute la requête Job Phase to Date 5 fois pour chaque Phase de Travail, elle s'exécute dans un laps de temps raisonnable. Toutefois, si j'exécute la première requête Job To Date ci-dessous, il faut BEAUCOUP plus long. La deuxième version de la requête, qui utilise une variable de table au lieu d'une sous-requête, prend la bonne quantité de temps (c'est-à-dire la somme des 5 requêtes de phase de travail à jour). Pourquoi la version de la table prend-elle moins de temps et # lit-elle que la version de la sous-requête?
Version 1 - Durée: 210,225ms CPU: 206,203ms lit comme suit: 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 - Durée: 9654 CPU: 9593 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
La table sous-jacente pourrait avoir un index qui pourrait être utilisé - les variables de table n'ont pas/ne supportent pas d'index. –
Oui. Je pense que l'optimiseur suppose toujours une ligne dans la variable de table pour décider d'un plan d'exécution. –