直接使用 EF Core 记录数据库 SQL 查询执行时间

问题描述 投票:0回答:1

我目前正在从事一个项目,该项目测量 SQL 语句的执行时间(服务器端)并将结果可视化以与其他数据库进行比较。我正在使用 EF Core 6 和 SQL Server。

问题是 EF Core 日志执行时间与来自 SSMS 的时间完全不匹配,我想知道为什么? (因子> 10x)

我测量了两次执行时间(有第二个值)

  1. 一次使用 EF Core 记录器 (
    Microsoft.EntityFrameworkCore.Database.Command -> Executing DbCommand
    ) MS EF Core logging
  2. 和SSMS(在SQL语句之前/之后用
    set statistics time on/off

一个SQL语句的例子:

  • EF 核心:49-60 毫秒
  • SSMS:377-1551 毫秒
c# sql-server entity-framework-core ssms
1个回答
0
投票

简单地运行相同的查询两次保证无效值。数据库积极缓存数据,这意味着第二次查询将比第一次查询更快,因为数据已经加载到内存中。这就是为什么原始执行时间很少用于优化性能的原因。

最重要的是,结果取决于实际代码。 Find 实际上缓存了它加载的对象,因此在同一上下文中两次调用 Find 将返回已加载的对象。如果代码使用单例/共享 DbContext,它总是使用缓存数据。 DbContext 是一个工作单元,而不是数据库连接。

没有实际代码,只能猜测发生了什么。 正确 衡量数据库性能的方法是首先确保清除所有数据库缓冲区,然后然后 执行每个测试足够多次以获得具有统计意义的结果。衡量性能的常用方法是使用 BenchmarkDotNet 重复每个测试足够的次数以确保有效的结果。

与其使用 SSMS 来衡量“直接”性能,不如直接使用 ADO.NET。这允许通过代码运行测试并消除由于应用程序设置引起的差异。

一个可能的基准可能是这样的:

public class EFvsDirect
{
    string _connectionString;
    DbContextOptions<TestContext> _options;

    public class EFvsDirect()
    {
        _connectionString=".....";
        _options=new DbContextOptionsBuilder<TestContext>()
            .UseSqlServer(_connectionString).Options;
    }

    [IterationSetup]
    public void Setup()
    {
        var sql="DBCC DROPCLEANBUFFERS";

        using con=new SqlConnection(_connectionString);
        using var cmd=new SqlCommand(sql,con);
        con.ExecuteNonQuery();
    }

    [Benchmark]
    public void DirectQuery()
    {
        var sql="SELECT * FROM Products WHERE ID=5";

        using con=new SqlConnection(_connectionString);
        using var cmd=new SqlCommand(sql,con);

        //Execute the query
        using var reader=con.ExecureReader();
        //Load results
        var table=new DataTable();
        table.Load(reader);
    }

    [Benchmark]
    public void EfQuery()
    {
        using ctx=new TestContext(_options);
        var product=ctx.Products.Find(5);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.