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. var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); 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 => |
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:
C# - Lendo e escrevendo em arquivos textos e binários
C# - Entendo o I/O na plataforma .NET
C# - Fluxo assíncrono ou async streams
C#- Apresentando Streams assíncronos