Entity Framework Arithabort, mas ainda consulta é lento

0

Pergunta

Eu tenho uma consulta simples

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

A tabela tem apenas 3 Colunas e 10 linhas de dados.

Quando eu tentei executar a consulta da Net 5 projeto é de cerca de 2,3 segundos para o primeiro tempo e 500ms (+- 100) para pedidos subsequentes. Quando eu bati o mesmo pedido no SSMS está retornando em quase nenhum momento (45ms, como visto no sql profiler).

Eu tenho implementado ARITHABORT na EF, a partir de aqui

Quando eu vejo no SQL Profiler é a definição de ARITHABORT, mas ainda a consulta demora o mesmo tempo para a primeira solicitação e pedidos subsequentes.

sql profiler screen shot

Como posso alcançar a mesma velocidade de SSM velocidade de consulta. Eu preciso de consulta para executar realmente velocidade do meu projeto tem requisito para o retorno da resposta em 1 segundo (Precisa fazer pelo menos 5 simples chamadas de DB...se 1 chamada 500ms, em seguida, é a travessia de 1 segundo requisito)

Editar

Tentei com o mesmo ADO.Net. O tempo de execução teve como visto no SQL Profiler é de 40 ms, onde, como, quando chegou o código é quase 400ms. Tanta diferença

        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

Melhor resposta

0

A sua "primeira vez" cenário geral é o de inicialização estático de DbContext. Este é o lugar onde o DbContext funciona o seu mapeamentos para o primeiro tempo e vai ocorrer quando a primeira consulta é executada. A abordagem típica para evitar que isto ocorra por um usuário é ter um simples "warm up" consulta que é executado quando o serviço é iniciado.. Por exemplo após o seu inicializa o serviço, basta colocar algo como o seguinte:

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

Isso também serve como um quick start-up de verificação de que o banco de dados está acessível e de responder. A consulta em si vai fazer uma operação rápida, mas o DbContext vai resolver seus mapeamentos este tempo, para qualquer recém-gerado DbContext instâncias irá responder sem incorrer em que o custo durante um pedido.

Como para matérias de desempenho, se não for uma consulta que é de se esperar um tempo e amarrar um pedido, não torná-lo async. Solicitações assíncronas são não mais rápido, eles são, na verdade, um pouco mais lento. Usando async pedidos contra o DbContext é o de garantir o seu servidor web / thread de aplicação é sensível ao potencialmente caro banco de dados de operações de processamento. Se você deseja uma resposta o mais rápido possível, utilize uma chamada síncrona.

Em seguida, verifique se todos os campos que você está filtrando contra, neste caso, Moeda, são indexados. Ter um campo chamado Moeda de sua entidade como uma Seqüência de caracteres em vez de um CurrencyId FK (int) apontando para uma Moeda de um registro já é um extra de indexação de despesas como índices em números inteiros são menores e com mais rapidez do que as seqüências de caracteres.

Você também não precisa se preocupar com AsNoTracking quando utilizar um Count consulta. AsNoTracking aplica-se somente quando você estiver retornando entidades (ToList/ToArray/Single/Firstetc.) para evitar o DbContext segurando uma referência para a entidade retornada. Quando você usa Count/Any ou projeção para retornar as propriedades de entidades usando Select não há nenhuma entidade voltou para a pista.

Também considerar a latência da rede entre o lugar onde o código de sua aplicação está em execução e o servidor de banco de dados. Eles são a mesma máquina ou há uma conexão de rede em jogo? Como isso se compara quando você estiver executando uma consulta do SSMS? Usando um profiler, você pode ver o que o SQL EF é, na verdade, a enviar para o banco de dados. Tudo o resto, em termos de tempo é um custo de: Chegando a solicitação para o banco de dados, Obter os dados resultantes para o solicitante, a análise dessa resposta. (Se no caso você estiver retornando entidades, alocação, preencher, verificar a existência de referências existentes, etc... No caso de contagens, etc. verificação de referências existentes)

Por fim, para garantir que você está recebendo o máximo desempenho, garantir que o seu DbContexts vidas são curtas. Se um DbContext é mantido aberto e teve um número de acompanhamento de consultas executa no (Seleção de entidades sem AsNoTracking) as controladas referências de entidade acumulam e podem ter um impacto negativo no desempenho em futuras consultas, mesmo se você usar AsNoTracking EF olha para verificar é controlado referências para as entidades que podem ser aplicável/relacionados ao seu novo consultas. Muitas vezes eu vejo os desenvolvedores assumem que DbContexts são "caros" para optar por eles para instanciá-tão pouco quanto possível para evitar esses custos, só para acabar tornando as operações mais caro ao longo do tempo.

Com tudo isso considerado, EF nunca vai ser tão rápido como matérias-SQL. É um ORM projetado para fornecer conveniência .Net applications, quando se trata de trabalhar com dados. Que a conveniência de trabalhar com classes de entidade em vez de desinfecção e escrever o seu próprio raw SQL toda vez que vem com um custo.

2021-11-23 21:59:24

na medida do seu comentário sobre a latência de Rede, tanto SSMS & Net Código está na minha máquina..db no servidor...e outras coisas que eu tenho apenas uma consulta (este é um POC). Assim, com a mesma latência de rede SSMS é capaz de buscar em 40 ms, onde, como Líquido Código está tomando 500ms.....até tentei com ADO.NET como visto na questão, ambos estão a tomar 500ms
CrazyMonk

Em outros idiomas

Esta página está em outros idiomas

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