Entity Framework Arithabort, dar încă interogare este lent

0

Problema

Am o intrebare simpla

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

Tabelul are doar 3 Coloane și 10 rânduri de date.

Când am încercat pentru a executa interogarea de la Net 5 proiect este de a lua în jurul valorii de 2,3 secunde pentru prima dată și 500ms (+- 100) pentru cererile ulterioare. Când m-am lovit de aceeași cerere în SSMS se întoarce în aproape nici un timp (45ms cum se vede în sql profiler).

Am implementat ARITHABORT în EF de aici

Când văd în SQL Profiler este setarea ARITHABORT dar încă interogare nevoie de același timp de la prima solicitare și cererile ulterioare.

sql profiler screen shot

Cum pot atinge viteza fel ca SSMS viteza de interogare. Am nevoie de interogare pentru a rula într-adevăr viteza ca proiectul meu are obligația de a returna răspuns în 1 secundă (Nevoie pentru a face cel putin 5 simplu DB apeluri...dacă 1 apel ia 500ms atunci este de trecere 1 de-a doua cerință)

Edit

A încercat chiar și cu ADO.Net. Timpul de executie a luat cum se vede în SQL Profiler este 40ms în cazul în care, ca atunci când se ajunge la codul este aproape de 400 ms. O diferență atât de mult

        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

Cel mai bun răspuns

0

"Prima ta rula" scenariu este, în general, o singură dată static de initializare a DbContext. Acest lucru este în cazul în care DbContext lucrările sale mapări pentru prima dată și va apărea atunci când prima interogare este executat. Abordarea tipică pentru a evita acest lucru produce pentru un utilizator este de a fi un simplu "încălzească" interogare care se execută atunci când serviciul pornește.. De exemplu, după serviciul initializeaza, pur și simplu pune ceva de genul următor:

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

Acest lucru, de asemenea, servește ca o pornire rapidă, verificați că baza de date este accesibilă și de a răspunde. Interogarea se va face foarte rapid, dar DbContext va rezolva operatori la acest moment, astfel încât orice nou generat DbContext cazuri va răspunde, fără a suporta acest cost în timpul o cerere.

Ca prime de performanță, dacă nu este o interogare care este de așteptat să dureze un timp și cravată o cerere, nu face async. Cereri asincrone sunt nu mai repede, ele sunt de fapt un pic mai lent. Folosind async cererile împotriva DbContext este vorba despre asigurarea ta de server web / aplicație fir este receptiv în timp ce potențial costisitoare operațiuni de baze de date sunt de prelucrare. Dacă doriți un răspuns cât mai repede posibil, utilizați un sincron de apel.

Următor, să se asigure că orice domenii de filtrare împotriva, în acest caz, în Valută, sunt indexate. Având un câmp numit Moneda în entitate ca un Șir de caractere, mai degrabă decât un CurrencyId FK (int) arătând spre o Moneda de înregistrare este deja un plus de indexare detrimentul ca indicii sunt numere întregi mai mici/mai mari decât cele de pe siruri de caractere.

Ai, de asemenea, nu aveți nevoie să deranjez cu AsNoTracking atunci când se utilizează un Count de interogare. AsNoTracking se aplică numai atunci când se întorc entități (ToList/ToArray/Single/Firstetc.) pentru a evita având DbContext deține pe o referință la returnate entității. Atunci când utilizați Count/Any sau de proiecție să se întoarcă proprietăți de entități care utilizează Select nu există nici o entitate a revenit pentru a urmări.

De asemenea, ia în considerare rețeaua de latenta intre în cazul în care cererea dumneavoastră de cod se execută și serverul de baze de date. Sunt aceeași mașină sau există o conexiune de rețea în joc? Cum se compara asta atunci când se efectuează o SSMS interogare? Folosind un profiler puteți vedea ce SQL EF este de fapt trimite la baza de date. Totul în termeni de timp este un cost de: Obtinerea cererea DB, Obtinerea de rezultate date înapoi solicitantului, parsarea de răspuns. (Dacă, în cazul în care se întorc entități, alocarea, popularea, verificarea împotriva existente, referințe, etc... In cazul de capete de acuzare etc. verificarea existente trimiteri)

În cele din urmă, pentru a vă asigura că sunt obtinerea de performanțe de vârf, asigurați-vă că DbContexts vieți sunt păstrate pe termen scurt. Dacă un DbContext este ținut deschis și a avut un număr de urmărire a rula interogări împotriva în (Selectarea entităților fără AsNoTracking) cele urmărite referințe entitate se acumulează și poate avea un impact negativ asupra performanței viitoare interogări, chiar dacă utilizați AsNoTracking ca EF pare să verificați prin e urmărit referințe de entități care ar putea fi aplicabile/legate la noi interogări. De multe ori am vedea dezvoltatorii presupune DbContexts sunt "scumpe" astfel încât acestea să opteze pentru a instantia-le cât mai puțin posibil pentru a evita aceste costuri, doar pentru a sfârși prin a face operațiunile mai scump de-a lungul timpului.

Cu toate că a considerat, EF nu va fi niciodată la fel de repede ca materii prime SQL. Este o ORM conceput pentru a oferi confort sa .Net applications, atunci când e vorba de a lucra cu date. Care comoditate în lucrul cu clase entitate mai degrabă decât de igienizare și scrie propriile tale prime SQL de fiecare dată vine cu un cost.

2021-11-23 21:59:24

în măsura în comentariu cu privire la Rețeaua de latență ambele SSMS & Net Codul este de la masina mea..pb este de la serverul...și pentru alte lucruri am doar una interogare (aceasta este o POC). Deci cu aceeași latență de rețea SSMS este capabil de a aduce în 40ms unde ca Net Cod este de a lua 500ms.....chiar a încercat cu ADO.NET după cum se vede în cauză, ambele sunt luați 500ms
CrazyMonk

În alte limbi

Această pagină este în alte limbi

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