Entity Framework Arithabort, mais encore de la requête est lent

0

La question

J'ai une requête simple

var count =  await _context.ExchangeRate.AsNoTracking().CountAsync(u => u.Currency == "GBP");

La table a seulement 3 Colonnes et 10 lignes de données.

Quand j'ai essayé d'exécuter la requête de Net 5 projet c'est de prendre environ 2,3 secondes pour la première fois et 500ms (+- 100) pour les demandes suivantes. Quand j'ai frappé la même demande dans SSMS, il est de retour dans presque pas de temps (45ms comme on le voit dans le générateur de profils sql).

J'ai mis en œuvre ARITHABORT en EF à partir d' ici

Quand je vois dans le générateur de profils SQL, il est le réglage de ARITHABORT, mais encore la requête prend le même temps pour la première demande et les demandes ultérieures.

sql profiler screen shot

Comment puis-je atteindre la vitesse même que SSMS vitesse de requête. J'ai besoin de la requête à exécuter, vraiment la vitesse que mon projet a obligation pour le retour de la réponse en 1 seconde (il Faut faire au moins 5 simple DB appels...si 1 appel prend 500ms puis c'est la traversée de 1 seconde exigence)

Modifier

Essayé avec le même ADO.Net. Le temps d'exécution a pris comme on le voit dans le générateur de profils SQL est de 40ms, où, comme lorsqu'il atteignit le code, il est presque 400ms. Autant de différence

        using (var conn = new SqlConnection(connectionString))
        {
            var sql = "select count(ExchangeRate) as cnt from ExchangeRate  where Currency = 'GBP'";

            SqlCommand cmd = new SqlCommand();

            cmd.CommandText = "SET ARITHABORT ON; " + sql;
            cmd.CommandType = CommandType.Text;
            cmd.Connection = conn;
            conn.Open();
            var t1 = DateTime.Now;
            var rd =  cmd.ExecuteReader();
            var t2 = DateTime.Now;
            TimeSpan diff = t2 - t1;

           Console.WriteLine((int)diff.TotalMilliseconds);
          
          while (rd.Read())
          {
               Console.WriteLine(rd["cnt"].ToString());
          }
            conn.Close();
        }
1

La meilleure réponse

0

Votre "première" le scénario est généralement l'initialisation statique de la DbContext. C'est là que le DbContext œuvres de ses mappages pour la première fois et se fera lors de la première requête est exécutée. L'approche typique pour éviter que cela se produise pour un utilisateur est de disposer d'un simple "réchauffer" requête qui s'exécute au démarrage du service.. Par exemple après votre service initialise, il suffit de mettre quelque chose comme ce qui suit:

// Warm up the DbContext
using (var context = new AppDbContext())
{
    var hasUser = context.Users.Any();
}

C'est aussi un démarrage rapide de vérifier que la base de données est accessible et de répondre. La requête elle-même allons faire un très rapide de l'opération, mais la DbContext permettra de résoudre ses mappages à cette heure si tout nouvellement générés DbContext instances de répondre sans encourir de ce coût lors d'une requête.

Comme pour les matières premières, les performances, si ce n'est pas une requête qui devrait prendre un certain temps et l'attacher à une demande, de ne pas le faire async. Des requêtes asynchrones sont pas plus rapides, ils sont en réalité un peu plus lent. À l'aide de async les demandes à l'encontre de la DbContext est de s'assurer que votre serveur web / application thread est sensible alors que potentiellement coûteuses opérations de base de données en cours de traitement. Si vous voulez une réponse aussi vite que possible, utilisez un appel synchrone.

Ensuite, assurez-vous que tous les champs d'un filtre contre, dans ce cas, Monnaie, sont indexés. Avoir un champ appelé Devise de l'entité comme une Chaîne plutôt qu'une CurrencyId FK (int) pointant vers un bureau de l'enregistrement est déjà un supplément d'indexation de la charge d'indices sur les entiers sont plus petits, plus rapide que celles sur les cordes.

Vous pouvez aussi ne pas besoin de s'embêter avec AsNoTracking lors de l'utilisation d'un Count de la requête. AsNoTracking s'applique uniquement lorsque vous êtes de retour entités (ToList/ToArray/Single/Firstetc.) pour éviter d'avoir le DbContext tenant sur une référence à l'entité renvoyée. Lorsque vous utilisez Count/Any ou de projection de renvoyer les propriétés d'entités à l'aide de Select il n'y a pas d'entité retourné à la piste.

Également envisager la latence du réseau, entre les où le code de votre application est en cours d'exécution et le serveur de base de données. Sont-ils la même machine ou est-il un réseau de connexion dans le jeu? Comment cela se compare lorsque vous effectuez une SSMS requête? À l'aide d'un profileur vous pouvez voir ce que SQL EF est en fait de l'envoi à la base de données. Tout le reste, en termes de temps un coût: l'Obtention de la demande de la DB, Obtenir les données résultant de retour à la charge du demandeur, l'analyse de cette réponse. (Si dans le cas où vous êtes de retour entités, l'allocation, l'alimentation, la vérification des contre références existantes, etc... Dans le cas de compte etc. la vérification des références existantes)

Enfin, pour vous assurer d'obtenir le rendement maximum, s'assurer que votre DbContexts des durées de vie sont de courte durée. Si un DbContext est maintenue ouverte et a eu un certain nombre de suivi des requêtes exécutées sur dans (de la Sélection des entités sans AsNoTracking) de ceux suivis des références d'entité s'accumulent et peuvent avoir un impact négatif sur les performances futures requêtes, même si vous utilisez AsNoTracking que EF semble à vérifier à travers un suivi des références à des entités qui pourraient être applicables/lié à votre nouvelle requêtes. De nombreuses fois, je vois les développeurs assumer DbContexts sont "cher", de sorte qu'ils optent pour instancier aussi peu que possible pour éviter ces coûts, pour finir, ce qui rend les opérations plus cher au fil du temps.

Avec tout ce que considéré, EF ne sera jamais aussi rapide que les matières premières SQL. C'est un ORM conçu pour fournir la commodité pour .Net applications quand il s'agit de travailler avec les données. Que la convivialité dans le travail avec les classes d'entité plutôt que de la désinfection et de la rédaction de votre propre cru, SQL à chaque fois un coût.

2021-11-23 21:59:24

en ce qui concerne votre commentaire concernant la latence du Réseau, à la fois SSMS & Net Code est dans ma machine..db est dans le serveur...et pour d'autres choses je n'ai qu'une requête (c'est un POC). Donc, avec la même latence du réseau SSM est capable d'aller chercher dans 40ms où Net Code est 500ms.....même essayé avec ADO.NET comme on le voit dans la question, les deux sont la prise de 500ms
CrazyMonk

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................