EF Core - Definindo o tamanho do batch de instruções
 Hoje veremos o recurso batching de instruções do EF Core que podemos usar para obter um melhor desempenho.

Desde as suas primeiras versões o EF Core oferece o recurso de batching de instrução ou declaração.

Este recurso significa que o EF Core não envia comandos individuais para cada instrução de inserção/atualização/exclusão. Ele vai agrupar várias instruções em uma única viagem de ida e volta ao banco de dados. (O EF 6 não suportava este recurso.)

Atualmente, não há um tamanho de lote padrão (limitado pela plataforma de banco de dados), no entanto, é provável que haja um 'ponto ideal' para sua aplicação de talvez entre 20 a 50 inserções por instrução, que oferece o melhor desempenho.

Há muitos fatores em jogo, então é realmente uma questão de tentativa e erro para ver o que funciona melhor. Definir o tamanho do lote muito baixo resultará em muitas viagens de ida e volta, enquanto que se o tamanho do lote for definido muito alto (ou apenas deixado para o padrão), haverá menos viagens de ida e volta, mas o desempenho ainda poderá ser ruim, pois a consulta maior levará mais tempo para executar no servidor de banco de dados.


Definir o tamanho do lote pode ser feito no método OnConfiguring() ou na configuração do serviço do contexto, na classe Program ou no arquivo Startup, usando a propriedade MaxBatchSize que define o número máximo de instruções que serão incluídas em comandos enviados ao banco de dados durante SaveChanges() ou null se nenhum tiver sido definido.

 Vejamos um exemplo onde definimos que o EF Core deverá enviar no máximo 50 instruções em cada instrução SQL:

1- Usando o método OnConfiguring()

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
      options
         .UseSqlServer(
           "Data Source=<instancia_sqlserver>;Initial Catalog=DemoDB;Integrated Security=True",
             p => p.MaxBatchSize(50))
               .EnableSensitiveDataLogging();
}

2- Usando a classe Program  (no .NET 6.0)

 var builder = WebApplication.CreateBuilder(args);

 // Add services to the container.
 builder.Services.AddControllers();

 var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");

 builder.Services.AddDbContext<Contexto>(options =>
           options
           .UseSqlServer(connectionString, b=>
b.MaxBatchSize(50))
           );

 var app = builder.Build();
 ...

2- Usando a classe Startup método ConfigureServices (no .NET 5.0/6.0)

 ...
 public void ConfigureServices(IServiceCollection services)
 {
            services.AddControllersWithViews();

            string mySqlConnectionStr = Configuration.GetConnectionString("DefaultConnection");

            services.AddDbContext<AppDbContext>(options =>
                                  options
                                  .UseMySql(mySqlConnectionStr,
                                   ServerVersion.AutoDetect(mySqlConnectionStr),
                               
   b=>b.MaxBatchSize(10)));
 }

O EF Core vai acionar o agrupamento em lote das instruções em torno de 3 a 7 instruções.

Uma forma de desativar o batching é atribuir o valor 1 na propriedade MaxBatchSize(1).

Assim o valor 1 será definido como tamanho máximo do lote, o que significa que o lote agora teria apenas uma instrução. Para inserir 3 registros, haveria 3 instruções de inserção individuais.  Talvez essa não seja uma opção ideal.

Então qual seria o valor ideal de MaxBatchSize para ter um desempenho otimizado?

Nem muito baixo, nem muito alto!

Infelizmente, não há valor mágico.

Se você definir muito baixo, vai executar muitas viagens de ida e volta e poderá diminuir o desempenho geral. Se você definir muito alto, haverá menos viagens de ida e volta, mas poderá diminuir o desempenho geral, levando mais tempo para gravar no servidor.

Não existe um número perfeito, pois existem muitos fatores, como: Tamanho da coluna, Índices, Latência, Triggers, etc.

E estamos conversados...

"Então ele disse: "Jesus, lembra-te de mim quando entrares no teu Reino".
Jesus lhe respondeu: "Eu lhe garanto: Hoje você estará comigo no paraíso"."
Lucas 23:42,43

Referências:


José Carlos Macoratti