我目前正在从事一个项目,该项目测量 SQL 语句的执行时间(服务器端)并将结果可视化以与其他数据库进行比较。我正在使用 EF Core 6 和 SQL Server。
问题是 EF Core 日志执行时间与来自 SSMS 的时间完全不匹配,我想知道为什么? (因子> 10x)
我测量了两次执行时间(有第二个值)
Microsoft.EntityFrameworkCore.Database.Command -> Executing DbCommand
) MS EF Core loggingset statistics time on/off
)一个SQL语句的例子:
简单地运行相同的查询两次保证无效值。数据库积极缓存数据,这意味着第二次查询将比第一次查询更快,因为数据已经加载到内存中。这就是为什么原始执行时间很少用于优化性能的原因。
最重要的是,结果取决于实际代码。 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);
}
}