SQL Server Logging of database SQL query execution time directly with EF Core [closed]

cotxawn7  于 2023-05-16  发布在  其他
关注(0)|答案(1)|浏览(149)

Closed. This question is opinion-based . It is not currently accepting answers.

Want to improve this question? Update the question so it can be answered with facts and citations by editing this post .

Closed 12 hours ago.
Improve this question

I am currently working on a project that measures the execution time(Server-Side) of SQL statements and visualizes the result to compare it with other database. I am using EF Core 6 and SQL Server.

The problem is that the EF Core logs execution times does not match the times in any way, from SSMS and I wonder why? (factor > 10x)

I measured the execution time twice (to have a second value)

  1. Once with EF Core logger ( Microsoft.EntityFrameworkCore.Database.Command -> Executing DbCommand ) MS EF Core logging
  2. And with SSMS (before/after the SQL statement with set statistics time on/off )

Example for one SQL statement:

  • EF Core: 49-60 ms
  • SSMS: 377-1551 ms
dsekswqp

dsekswqp1#

Simply running the same query twice guarantees invalid values. Databases cache data aggressively which means the second query will be faster than the first simply because the data is already loaded in memory. That's why raw execution time is rarely used to optimize performance.

On top of that, results depend on the actual code. Find actually caches the objects it loads so calling Find twice in the same context will return the already loaded object. If the code uses a singleton/shared DbContext, it's always using cached data. A DbContext is a Unit-of-Work, not a database connection.

Without the actual code one can only guess what's going on. The correct way to measure database performance is to first ensure any database buffers are cleared and then execute each test enough times to get statistically meaningful results. The common way to measure performance is to use BenchmarkDotNet to repeat each test enough times to ensure valid results.

Instead of using SSMS to measure "direct" performance, one should use ADO.NET directly. This allows running the test through code and eliminates differences due to application settings.

One possible benchmark could look like this:

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);
    }
}

相关问题