Performance et compilation des fonctions
Bonjour,
Je révise le code d'un développeur junior et je vois cette fonction:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| ALTER FUNCTION [dbo].[RM_GetAvgDaysToPay]
(
-- Add the parameters for the function here
@CompanyID int
)
RETURNS float
AS
BEGIN
-- Declare the return variable here
DECLARE @AvgDaysToPay float
-- Add the T-SQL statements to compute the return value here
DECLARE @Ansonia float
DECLARE @Freight float
SET @Ansonia = (SELECT TOP(1) aci.AvgDaysToPay FROM AnsoniaCreditInfo aci INNER JOIN CompanyDocketNumbers cdn ON aci.DocketPrefix = cdn.Prefix AND aci.DocketNumber = cdn.DocketNumber WHERE cdn.CompanyID = @CompanyID AND cdn.Purpose IN (1,3) ORDER BY cdn.Purpose)
SET @Freight = (SELECT TOP(1) ci.AvgDaysToPay FROM CreditInformation ci INNER JOIN CompanyDocketNumbers cdn ON ci.DocketPrefix = cdn.Prefix AND ci.DocketNumber = cdn.DocketNumber WHERE cdn.CompanyID = @CompanyID AND ci.DocketNumber IS NOT NULL AND ci.DocketPrefix IS NOT NULL AND cdn.Purpose IN (1,3) ORDER BY cdn.Purpose)
SET @AvgDaysToPay =
CASE
WHEN @Ansonia IS NULL AND @Freight IS NULL THEN NULL
WHEN @Ansonia IS NOT NULL AND @Freight IS NOT NULL THEN CONVERT(float,(@Ansonia + @Freight)) / 2
WHEN @Ansonia IS NOT NULL THEN @Ansonia
WHEN @Freight IS NOT NULL THEN @Freight
END
-- Return the result of the function
RETURN @AvgDaysToPay
END |
Je me dis, plutôt que de lancer 2 requêtes et placer des valeurs en mémoire, je vais faire un seule et unique requête:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| ALTER FUNCTION [dbo].[RM_GetAvgDaysToPay2]
(
-- Add the parameters for the function here
@CompanyID int
)
RETURNS float
AS
BEGIN
RETURN
( SELECT TOP 1 CASE
WHEN aci.AvgDaysToPay IS NULL OR ci.AvgDaysToPay IS NULL THEN (ISNULL(aci.AvgDaysToPay, 0) + ISNULL(ci.AvgDaysToPay, 0))
ELSE (aci.AvgDaysToPay + ci.AvgDaysToPay) / 2
END AS AvgValue
FROM CompanyDocketNumbers cdn
LEFT JOIN AnsoniaCreditInfo aci ON cdn.DocketNumber = aci.DocketNumber AND cdn.Prefix = aci.DocketPrefix
LEFT JOIN CreditInformation ci ON cdn.DocketNumber = ci.DocketNumber AND cdn.Prefix = ci.DocketPrefix
WHERE cdn.CompanyID = @CompanyID
AND cdn.Purpose IN (1,3)
ORDER BY cdn.Purpose)
END |
Je lance les fonctions côte-à-côte en utilisant les bon vieux:
Code:
1 2
| SET STATISTICS IO ON
SET STATISTICS TIME ON |
1 - Les deux plans d'exécution sont identiques
2 - Les statistiques de TIME et IO sont à toute fin pratique semblables
Mon environnement:
Instance SQL Server 2008R2
Base en mode 90 (2005)
Ma question:
Est-ce que SQL Server arrive à optimiser le code des fonctions (et procédure stockées) à un point tel qu'il peut joindre deux requêtes distinctes en une seule?
Ou bien c'est mon optimisation 'manuelle' qui n'est pas bonne?
Je travaille avec MSSQL depuis la version 7 et j'ai peut-être des habitudes d'optmisation qui sont devenue superflues depuis.
Merci de m'éclairer à ce sujet.
Aussi, si vous avez des sources intéressantes sur la façon sont MSSQL compile les fonctions et l'évolution de ce processus depuis la version 7, j'apprécierais énormément. :P