【问题标题】:ef core slow Initialization of DbContext on a small datamodelef core slow 在小型数据模型上初始化 DbContext
【发布时间】:2021-08-09 16:40:22
【问题描述】:

我认为我的 DbContext 初始化存在问题。我知道很多人都在谈论它,但我可能做错了什么,因为这些答案与大上下文或大表(许多列或大量数据)有关。

在我的例子中,用户表由 30 列组成,而我只有 30 000 行。

当我启动应用程序或它被回收时,需要 22 秒才能获得第一个查询结果。

我添加了一些日志,据我了解,查询显然不是问题(您可以在下面找到这些日志)。当我将查询复制粘贴到 SSMS 中时,我会在不到一秒的时间内得到结果。第一次执行后,查询和一切几乎是“立即的”。所以,t问题将来自于上下文的初始化。

我用一些预编译的视图或类似的东西读到它可能会更快。我真的很惊讶,只有那张“小”桌子我需要特殊处理才能获得可接受的性能。这就是为什么我认为我错过了一些东西。

我的应用程序在 .net core 3.1 中,我使用的是 Entity Framework Core 5.0.8

在我的 ConfigureService 中,我有:

services.AddDbContext<DbContext>(options =>
            options.UseSqlServer(serviceConfiguration.ConnectionString));

我的 DbContext:

public class DbContext : DbContext
{
    private readonly ILoggingService<DbContext> _loggingService;
    private readonly ILoggerFactory _loggerFactory;

    public virtual DbSet<User> Users { get; set; }

    public DbContext(DbContextOptions<DbContext> options, ILoggingService<DbContext> loggingService, ILoggerFactory loggerFactory)
        : base(options)
    {
        _loggingService = loggingService;
        _loggerFactory = loggerFactory;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.EnableSensitiveDataLogging();
        optionsBuilder.EnableServiceProviderCaching();

        optionsBuilder.UseLoggerFactory(_loggerFactory);
        base.OnConfiguring(optionsBuilder);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        _loggingService.LogError("Begin model creating");
        modelBuilder.Entity<User>(entity =>
        {
            entity.HasKey(u => u.UserId);
            entity.ToTable("User");
        });
        _loggingService.LogError("End model creating");
    }
}

2021-08-09 15:28:30.830|WARN|Microsoft.EntityFrameworkCore.Model.Validation|敏感数据记录已启用。日志条目和异常消息可能包括敏感的应用程序数据;此模式只能在开发期间启用。|url:|action:UsersController.CreateUser

2021-08-09 15:28:30.957|INFO|Microsoft.EntityFrameworkCore.Infrastructure|Entity Framework Core 5.0.8 使用提供程序“Microsoft.EntityFrameworkCore.SqlServer”初始化“DbContext”,选项:SensitiveDataLoggingEnabled |url:|action :UsersController.CreateUser

2021-08-09 15:28:52.702|INFO|Microsoft.EntityFrameworkCore.Database.Command|执行 DbCommand (53ms) [Parameters=[@__username_0='' (Size = 4000)], CommandType='"Text "', 命令超时='30'] SELECT TOP(1) [u].[UserId], [u].[Email], [u].[Firstname], [u].[Username] FROM [用户] AS [u] WHERE ([u].[Username] = @__username_0) AND ([u].[StatusId] > 0)|url:|action:UsersController.CreateUser

2021-08-09 15:28:52.973|INFO|Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker|在 23053.3706ms|url:|action:UsersController.CreateUser 中执行的操作 UsersController.CreateUser

【问题讨论】:

  • 您是否对应用程序进行了概要分析以查看时间花费在哪里?
  • 这里的未知数真的太多了。可能只是你的机器很慢。
  • “据我了解,查询不是问题”。 EF Core 通常不会初始化上下文,直到您尝试将其用于某事;我从日志中可以看到,从实际初始化到它完成运行查询需要大约 22 秒;您如何确定查询不是问题?如果您在本地安装了用于开发/测试的 SQL Server,则可以使用 Developer 版本,其中包括 SQL Server 分析器。您可以使用它来查看该 SQL 语句是否真的很慢,尽管 30,000 行并不多。
  • 我在我的问题中添加了一些精确度。就像我所说的那样,它与我的机器无关,因为在第一次午餐后它比第一次快得多,所以即使我的机器速度很慢,仍然存在很大差异(1 秒与 22 秒)。 “据我了解,查询不是问题”-> 在 SSMS 中复制/粘贴查询时,它总是很快。所以它纯粹与.net代码有关。
  • 如果关闭日志记录会发生什么?这可能会增加一次性初始化成本。 DbContext 初始化成本通常取决于表的数量/正在初始化的架构的复杂性,这对于您的示例来说应该不是问题。如果像日志记录这样的事情确实会产生类似的一次性成本,那么在这些情况下应该考虑相同的“热身”过程。 (本质上是在应用程序/站点的最早初始化点启动一个简单的 Count()/Any() 查询。)

标签: performance entity-framework asp.net-core .net-core entity-framework-core


【解决方案1】:

经过更多分析,即使在 IIS 中空闲时间为 0,在 5-10 分钟不活动后也会出现问题。我在连接字符串中发现了参数 Min Pool Size,它解决了我的 5 不活动问题-10 分钟。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多