2010-11-08 4 views
2

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 

Répondre

1

Vérifiez le plan d'exécution réel pour chacun dans Management Studio - qui vous dira où le coût est attribué pour chacun.

1

La variable de table ne peut pas être optimisée par le moteur de recherche, où la table sous-jacente (lorsqu'elle est utilisée directement) peut.

+0

La table sous-jacente pourrait avoir un index qui pourrait être utilisé - les variables de table n'ont pas/ne supportent pas d'index. –

+0

Oui. Je pense que l'optimiseur suppose toujours une ligne dans la variable de table pour décider d'un plan d'exécution. –