2012-10-01 4 views
3

Nous utilisons Entity Framework 5.0.0, première approche de base de données. J'ai importé deux fonctions ITVF (Inline Table-Value) en ligne dans mon EDMX qui renvoient des IQueryable. Une fois retourné, nous faisons le plus souvent un certain type d'opérations sur eux, comme .Skip(). Take()Performances des fonctions EF et table

La performance est bonne, pour quelques heures au moins. Sans rien faire (au moins ce que je sais), la performance se dégrade pendant la nuit.

Dans un premier temps, la requête prendra environ 500 ms à exécuter. Au cours de la nuit, les performances se dégradent à un niveau où la requête renvoie une exception Timeout (30-60secondes). Cela ne se produit lorsque la fonction de table est exécutée à partir du code, comme:

IQueryable<MyResult> results = 
      _context.MyTableFunction("searchforthis") 
       .Skip(currentPagingPosition*20).Take(20); 

(Ce n'est pas la première fois que nous courons la requête que cela se produit)

Si nous courons cependant la même fonction de table direcly de SQL Server Management Studio, la requête s'exécutera dans ~ 500ms.

Si je « Resave » la fonction de table comme:

ALTER FUNCTION [dbo].[MyTableFunction]...... 

sans faire des changements « réels », il va instantanément d'être 500ms rapide, même lorsqu'il est appelé à partir du code.

Ai-je manqué quelque chose d'évident, des idées?

+1

reniflement des paramètres. [Lent dans l'application, rapide dans SSMS? Comprendre les performances des mystères] (http://www.sommarskog.se/query-plan-mysteries.html) –

+0

Les problèmes de performances se manifestent-ils par une utilisation élevée de l'unité centrale/de la mémoire à partir de l'application? –

+2

duplication possible de [sql s'exécute rapidement dans ssms lent dans asp.net] (http://stackoverflow.com/questions/10175422/sql-runs-fast-in-ssms-slow-in-asp-net) –

Répondre

0

J'ai donc essayé d'ajouter l'option Recompiler à un TVF en ligne, mais il semble que ce n'est pas autorisé. La seule manière que je trouvais autour de c'était de créer une fonction multi-instruction, mais ils ont leurs inconvénients:

Configuration

CREATE Table MyTest 
(
    ID INT PRIMARY KEY Identity, 
    SomeValue VARCHAR(MAX), 
    UpdateDate Date 
) 
CREATE INDEX IDX_MyTest_UpdateDate 
ON MyTest(UpdateDate) 


GO 

Créer des fonctions

CREATE FUNCTION MyFunction(@FromDate date, @ToDate Date) 
RETURNS TABLE 
AS 
RETURN 
( 
    SELECT SomeValue, UpdateDate 
    FROM MyTest 
    WHERE UpdateDate >= @FromDate AND 
      UpdateDate <[email protected] 
    -- OPTION (RECOMPILE) **** NOT ALLOWED HERE** 
) 
GO 

CREATE FUNCTION MyFunction2(@FromDate date, @ToDate Date) 
RETURNS @retMyFunction TABLE 
    (
     SomeValkue VARCHAR(MAX), 
     UpdateDate Date 
    ) 
AS 
BEGIN 
    INSERT INTO @retMyFunction 
    SELECT SomeValue, UpdateDate 
    FROM MyTest 
    WHERE UpdateDate >= @FromDate AND 
      UpdateDate <[email protected] 
    OPTION (RECOMPILE); 

    RETURN; 
END 
GO 

Load Data

INSERT INTO MyTest (SomeValue, UpdateDate) 
SELECT CAST(X.n * Y.n * z.n AS VARCHAR(Max)), DATEADD(D, ROW_NUMBER() OVER (ORDER BY X.n), '2010-01-01') 
FROM (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) X(n) 
CROSS APPLY (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) Y(n) 
CROSS APPLY (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) Z(n) 

Test

-- Index Scan 
SELECT * FROM MyTest 
WHERE UpdateDate > '2010-01-02' AND UpdateDate < '2020-01-01' 
-- Index Seek 
SELECT * FROM MyTest 
WHERE UpdateDate > '2010-01-02' AND UpdateDate < '2010-01-05' 


-- Index Scan 
SELECT * 
FROM MyFunction('2010-01-02', '2020-01-01') 
-- Index Scan 
SELECT * 
FROM MyFunction('2010-01-02', '2010-01-05') 


-- Index Scan 
SELECT * 
FROM MyFunction2('2010-01-02', '2020-01-01') 
-- Index Seek 
SELECT * 
FROM MyFunction2('2010-01-02', '2010-01-05') 
+0

alors j'essaie de comprendre ce que vous vouliez dire par cette réponse, mais je ne sais pas si cela a résolu votre problème, vous dites simplement "ils ont leurs inconvénients". J'ai un problème très similaire et je n'arrive pas à trouver un moyen de le résoudre. –

+0

@GabrielEspinoza Je n'ai pas eu le problème Je répondais juste à la question (pas ma question!). Les inconvénients des fonctions multi-instructions sont qu'elles s'exécutent sur une base row-by-agonizing-row (un peu comme un curseur) et sont donc lentes sur les grands ensembles de données. À mon humble avis la meilleure option est d'écrire une procédure stockée pour retourner vos ensembles de données et d'utiliser OPTION RECOMPILE sur les déclarations individuelles du SP ou sur l'ensemble du SP. –

+0

croiriez-vous que si je vous dis que j'ai modifié la fonction inline sans aucun changement et que ça a fait l'affaire d'accélérer? - Je suppose que le reniflage des paramètres est vraiment une douleur dans le cul quand il échoue à optimiser le plan d'exécution. Ce serait bien d'avoir un peu de contrôle, comme sur les SP –

Questions connexes