web-dev-qa-db-fra.com

Entity Framework Vs Stored Procedures - Mesure de performance

J'essaie d'établir à quel point Entity Framework est plus lent que les procédures stockées. J'espère convaincre mon patron de nous laisser utiliser Entity Framework pour faciliter le développement.

Le problème est que j'ai exécuté un test de performance et il semble que EF soit environ 7 fois plus lent que les processus stockés. Je trouve cela extrêmement difficile à croire et je me demande si je manque quelque chose. Est-ce un test concluant? Puis-je faire quelque chose pour augmenter les performances du test EF?

        var queries = 10000;

        //  Stored Proc Test
        Stopwatch spStopwatch = new Stopwatch();
        spStopwatch.Start();
        for (int i = 0; i < queries; i++ )
        {
            using (var sqlConn = new SlxDbConnection().Connection)
            {
                var cmd = new SqlCommand("uspSearchPerformanceTest", sqlConn) { CommandType = CommandType.StoredProcedure };

                cmd.Parameters.AddWithValue("@searchText", "gstrader");
                sqlConn.Open();
                SqlDataReader dr = cmd.ExecuteReader();

                List<User> users = new List<User>();
                while (dr.Read())
                {
                    users.Add(new User
                    {
                        IsAnonymous = Convert.ToBoolean(dr["IsAnonymous"]),
                        LastActivityDate = Convert.ToDateTime(dr["LastActivityDate"]),
                        LoweredUserName = dr["LoweredUserName"].ToString(),
                        MobileAlias = dr["MobileAlias"].ToString(),
                        UserId = new Guid(dr["UserId"].ToString()),
                        UserName = (dr["UserName"]).ToString()
                    });
                }

                var username = users.First().UserName;
                sqlConn.Close();
            }
        }
        spStopwatch.Stop();
        Console.WriteLine("SP - {0} Queries took {1}", queries, spStopwatch.ElapsedMilliseconds );

        //  EF  Test
        Stopwatch entityStopWatch = new Stopwatch();

        var context = new SlxDbContext();
        var userSet = context.Set<User>();
        entityStopWatch.Start();
        for (int i = 0; i < queries; i++)
        {
            User user = userSet.Where(x => x.UserName == "gstrader").First();
        }

        entityStopWatch.Stop();
        Console.WriteLine("Entity - {0} Queries took {1}", queries, entityStopWatch.ElapsedMilliseconds);

Résultat:

SP - 10000 requêtes ont pris 2278

Entité - 10000 requêtes ont pris 16277

57
reach4thelasers

Vous pouvez effectuer certaines opérations pour optimiser votre requête. Ici sur MSDN vous pouvez trouver un bel aperçu.

Mais pour être honnête, une procédure stockée avec mappage manuel sera toujours plus rapide en termes de performances. Mais demandez-vous, quelle est l'importance de la performance? Dans la plupart des projets, le temps de développement est bien plus important que les performances. Qu'est-ce qui a été plus difficile à développer? La requête brute avec analyse ou la requête Entity Framework?

Les ORM ne sont pas conçus parce qu'ils fonctionnent bien mieux qu'une approche manuscrite. Nous les utilisons car le développement est tellement plus facile!

Si vous écrivez votre application avec Entity Framework et cachez toutes vos requêtes derrière un modèle de référentiel, vous pouvez développer très rapidement, puis, lorsque les performances deviennent un problème, mesurez votre application pour détecter le goulot d'étranglement. Peut-être que certaines de vos requêtes doivent être optimisées et peuvent être déplacées vers des procédures stockées et un mappage manuel.

81
Wouter de Kort

En accord avec @Wouter de Kort ... De plus, lorsque vous devez passer à des procédures, vous pouvez utiliser EF en conjonction avec des procédures pour faciliter la migration de l'une à l'autre.

Le passage aux procédures sera plus rapide dans une application typique si vous nifiez la fonctionnalité dans des procédures bien conçues. c'est-à-dire faire autant de travail que possible dans n appel sproc possible. Par exemple, dans une application MVC de panier d'achat lorsqu'un utilisateur clique sur le bouton de paiement, vous peut-être utilisez l'ORM pour quelque chose comme:

  1. rechercher l'authentification d'un utilisateur (la connexion est-elle toujours valide?)
  2. rechercher des autorisations (peuvent-ils acheter lesdits articles?, existe-t-il des exigences particulières?)
  3. recherchez les quantités en stock pour vous assurer qu'elles n'ont pas été épuisées pendant le processus
  4. écrire à DB pour réserver (retirer de l'inventaire disponible) les articles avant le paiement
  5. rechercher des informations de paiement
  6. enregistrement ...?

Ou cela peut être des étapes complètement différentes, mais dans tous les cas, le fait est que l'application MVC utilisera un ORM pour effectuer plusieurs appels à la base de données pour passer à l'étape suivante.

Si toute cette logique est encapsulée dans un sproc bien écrit, il n'y a qu'un seul appel au sproc et vous avez terminé. Avec la route MVC-ORM, les données doivent être copiées de la base de données vers le pilote et livrées à ORM (généralement via le net vers un hôte différent), puis lues par l'application MVC pour prendre une décision simple, puis répétées jusqu'à ce que toutes les étapes soient terminées . Dans le cas de l'utilisation d'un sproc qui encapsule cette étape de récupération, il y a beaucoup moins de copie et de déplacement de données à effectuer, moins d'E/S réseau, moins de changement de contexte, etc.

Pensez à la solution MVC-ORM de cette façon. La personne "A" ne connaît que les faits et la personne "B" a tout le sens pour prendre des décisions avec des faits donnés qu'il ne pose pas. La personne "B" envoie un e-mail à "A" pour les faits. Sur la base de la réponse de "A", "B" pourrait demander quelques faits supplémentaires avant de prendre une décision. C'est beaucoup de messages de va-et-vient.

Si vous avez une personne qui a tous les faits et les connaissances nécessaires pour prendre des décisions, il vous suffit de poser une question et leur cerveau traitera tout en interne pour trouver une réponse. Aucune délibération avec une autre personne n'est impliquée. Naturellement, ça va être plus rapide.

Cela ne veut pas dire que c'est nécessairement mieux. Séparer les faits de la décision signifie que ces composants sont remplaçables/testables séparément, cependant, si vous êtes marié à votre MVC et à votre base de données, ce n'est pas un problème.

D'un autre côté, de nombreux fans de MVC détestent écrire SQL, donc ils envisagent de placer toute logique de décision dans SQL comme une catastrophe naturelle. Pour ces personnes, il est impératif d'avoir une logique écrite dans le même langage que le MVC utilise car cela accélère le développement pour eux. Dans certains cas, il s'agit également d'un "non-problème" car dans le cas de certains RDMBS, vous pouvez écrire des sprocs dans le même langage que celui utilisé par le MVC (exemples: .Net - les sprocs SQL Server peuvent être écrits en C # et utiliser .Net; Les fonctions Postgresql (pas de sprocs) peuvent être écrites en Perl, Python, PHP et. Al) L'avantage dans ce cas est que vous pouvez avoir des sprocs rapides qui encapsulent plusieurs étapes en un seul appel et vous pouvez utiliser un langage de programmation que vous êtes déjà rapide à coder.

10
MikeM

Il est important de noter que

À partir de .NET Framework 4.5, les requêtes LINQ sont mises en cache automatiquement . Cependant, vous pouvez toujours utiliser les requêtes LINQ compilées pour réduire ce coût dans les exécutions ultérieures et les requêtes compilées peuvent être plus efficaces que les requêtes LINQ qui sont automatiquement mises en cache.

à partir des requêtes compilées MSDN (LINQ vers les entités)

2
Daniel