2009-04-16 3 views
1

Y a-t-il un moyen d'optimiser cette fonction UDF horrible et inefficace dans SQL Server 08. Je suis assez nouveau pour les UDF et surtout pour les optimiser.Comment puis-je optimiser cette fonction définie par l'utilisateur horriblement inefficace dans SQL Server 08

MISE À JOUR: Devrais-je envoyer une colonne à une fonction comme celle-ci si je voulais l'exécuter sur chaque ligne et chaque colonne d'une requête? Y a-t-il une meilleure façon de s'y prendre?

Merci Vous

** @value (float) et @fieldname (varchar (40)) sont des paramètres d'entrée **

BEGIN 
    DECLARE @UT integer, @FRM integer, @TO integer, @FACTOR float 

    select @UT = [UF_UT_ID] FROM dbo.UNIT_FIELDS where [UF_FIELD][email protected] 
    select @FRM = [UT_UN_ID_INTERNAL_UNITS] from dbo.UNIT_TYPES where [UT_ID][email protected] 
    select @TO = [UT_UN_ID_DISPLAY_UNITS] from dbo.UNIT_TYPES where [UT_ID][email protected] 
    select @FACTOR = [UC_SLOPE] from dbo.UNIT_CONVERSIONS where [UC_UN_ID_UNIT_FROM][email protected] and [UC_UN_ID_UNIT_TO][email protected] 

    -- Return the result of the function dbo. 
    RETURN @FACTOR*@value 
END 
+0

Comment savez-vous que cette UDF est inefficace? Avez-vous vu quelque chose dans SQL Profiler? – MedicineMan

Répondre

1

Étape 1 serait d'exécuter chaque sélectionner et voir où le goulot d'étranglement est.

3

Si vous pouvez joindre les trois tables en fonction des relations PK/FK, vous pouvez réduire la requête à une seule sélection. Sinon, la seule optimisation immédiatement évidente consiste à attribuer @FRM et @TO en une seule instruction select:

select @FRM = [UT_UN_ID_INTERNAL_UNITS], @TO = [UT_UN_ID_DISPLAY_UNITS] from dbo.UNIT_TYPES where [UT_ID][email protected] 
2

Un candidat classique pour une fonction de table en ligne ...

Quelque chose comme:

ALTER FUNCTION fnName(@value float, @fieldName VARCHAR(100)) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT @value * 
     (SELECT conv.[UC_SLOPE] from dbo.UNIT_CONVERSIONS conv 
     JOIN dbo.UNIT_TYPES UT_UN_ID_INTERNAL_UNITS ON where [UC_UN_ID_UNIT_FROM]=UT_UN_ID_INTERNAL_UNITS.[UT_ID] 
     JOIN dbo.UNIT_TYPES UT_UN_ID_DISPLAY_UNITS ON where [UC_UN_ID_UNIT_TO]=UT_UN_ID_DISPLAY_UNITS.[UT_ID] 
     JOIN dbo.UNIT_FIELDS fields ON (UT_UN_ID_INTERNAL_UNITS.[UT_ID] = fields.[UF_UT_ID]) AND (UT_UN_ID_DISPLAY_UNITS.[UT_ID] = fields.[UF_UT_ID]) 
     WHERE ([UF_FIELD][email protected]) 
     ) 
) 
0

Une petite chose que vous pouvez faire:

select @FRM = [UT_UN_ID_INTERNAL_UNITS] from dbo.UNIT_TYPES where [UT_ID][email protected] 
select @TO = [UT_UN_ID_DISPLAY_UNITS] from dbo.UNIT_TYPES where [UT_ID][email protected] 

Si je lis correctement le cela être le même que:

select @TO = [UT_UN_ID_DISPLAY_UNITS], 
     @FRM = [UT_UN_ID_INTERNAL_UNITS] 

from dbo.UNIT_TYPES where [UT_ID][email protected] 

Pourquoi exécuter une sélection deux fois sur le même enregistrement?

0

Cela doit réécrite en utilisant JOIN « s:

SELECT c.UC_SLOPE * @value 
FROM unit_fields f 
JOIN unit_types t 
ON  t.UT_ID = f.UF_UT_ID 
JOIN unit_conversions c 
ON  c.UC_UN_ID_UNIT_FROM = t.UT_UN_ID_INTERNAL_UNITS 
     AND c.UC_UN_ID_UNIT_TO = t.UT_UN_ID_DISPLAY_UNITS 
WHERE f.UF_FIELD = @field_name 
0
BEGIN 
    DECLARE @FACTOR float 

    select @factor = UC.UC_SLOPE 
     from dbo.UNIT_CONVERSIONS UC, 
      dbo.UNIT_TYPES  UT, 
      dbo.UNIT_FIELDS  UF 
     where [email protected] 
     and UT.UT_ID = UF.UF_UT_ID 
     and UC.UC_UN_ID_UNIT_FROM = UT.UT_UN_ID_INTERNAL_UNITS 
     and UC.UC_UN_ID_UNIT_TO = UT.UT_UN_ID_DISPLAY_UNITS 


    -- Return the result of the function dbo. 
    RETURN @FACTOR*@value 
END 
0

Vous pouvez essayer cela comme tout une requête:

--Decalre Factor var 
DECLARE @FACTOR float 

SELECT @FACTOR = [UC_SLOPE] 
FROM dbo.UNIT_CONVERSIONS uc 
--Join the Unit Types table to Unit Conversions on the old From & To types 
INNER JOIN dbo.UNIT_TYPES ut ON 
    ut.[UT_UN_ID_DISPLAY_UNITS] = uc.[UC_UN_ID_UNIT_TO] 
    AND ut.[UT_UN_ID_INTERNAL_UNITS] = uc.[UC_UN_ID_UNIT_FROM] 
--Join the Unit Files on the Unit Types 
INNER JOIN dbo.UNIT_FIELDS uf ON 
    uf.[UF_UT_ID] = ut.[UT_ID] 
WHERE uf.[UF_FIELD][email protected] 

-- Return the result of the function dbo. 
RETURN @FACTOR*@value