【愚公系列】2023年01月 .NET/C#知识点-EF Core性能优化之显示编译

举报
愚公搬代码 发表于 2023/01/31 21:39:57 2023/01/31
【摘要】 前言性能优化,简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短。对于EF Core的查询优化其实也是多种多样的,性能优化是在特定的情况下的特定解决方案,下面着重介绍EF Core的显示编译查询 1.显示编译的概念EF Core对我们查询的表达式的编译使用了缓存,当你查询代码需要重用以前执行的查询时,EF Core将使用哈希查找并从缓存中返回已编译的查...

前言

性能优化,简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短。

对于EF Core的查询优化其实也是多种多样的,性能优化是在特定的情况下的特定解决方案,下面着重介绍EF Core的显示编译查询

1.显示编译的概念

EF Core对我们查询的表达式的编译使用了缓存,当你查询代码需要重用以前执行的查询时,EF Core将使用哈希查找并从缓存中返回已编译的查询。如果能直接对查询进行编译,并跳过哈希的计算和缓存查找那么效率是否会提高呢?这就是显示编译。

说白了也就是跳过查找的过程,而且使用场景如下:

  • EF Core,还不支持编译查询返回集合类型。
  • 在数据量大的时候使用,比如查询大于一百万次时候大约回快6倍,一万次大约是2倍左右。

一、Core性能优化之显示编译

本文主要是内存数据库的方式来测试显示编译查询的性能,避免了其他因素。

显示编译的两个方法如下:

EF.CompileQuery()//同步方法
EF.CompileAsyncQuery()异步方法

这两个方法允许您定义一个已编译的查询,然后通过调用一个委托调用它。

1.安装

install-package Microsoft.EntityFrameworkCore.InMemory

在这里插入图片描述

2.注入

services.AddDbContext<TestDbContext>(options => {
     options.UseInMemoryDatabase(new Guid().ToString());
});//Guid是内存表名称

在这里插入图片描述

3.创建数据库上下文类

public class Team
{
    public int Id { set; get; }
    public string Name { set; get; } 
    public int age{set; get;}
}

在这里插入图片描述

//建立上下文,并加入Team表
public class TestDbContext : DbContext
{
    public TestDbContext(DbContextOptions<TestDbContext> options) : base(options)
    {
    }
    public DbSet<Team> Teams { get; set; }
    public void FillCategories()//插入内存数据库里
    {
        var Team = new List<Team>();
        for (int i = 0; i < 100000; i++)
        {
            Teams.Add(new Team { Id = i, Name = "张山", age = i + 1 });
        }
        Teams.AddRange(Team);
        SaveChanges(true);
    }
}

在这里插入图片描述

4.创建查询控制器类

[ApiController]
[Route("[controller]/[action]")]
public class TeamsCompileQueryController : ControllerBase
{
    public TestDbContext teamContext;
    public TeamsCompileQueryController(TestDbContext teamContext)
    {
        this.teamContext = teamContext;
    }
    [HttpGet(Name = "CompiledQuery")]
    public void CompiledQuery()
    {
        Func<TestDbContext, Team> compileQuery = EF.CompileQuery((TestDbContext context) =>
            context.Teams.OrderBy(o => o.Id).FirstOrDefault())!;
        var stopWatch = new Stopwatch();
        teamContext.Database.EnsureDeleted();
        teamContext.Database.EnsureCreated();
        stopWatch.Restart();
        for (var i = 0; i < 100; i++)
        {
            var blog = compileQuery(teamContext);
        }
        stopWatch.Stop();
        Console.WriteLine("显示编译查询:" + stopWatch.Elapsed);
    }
    [HttpGet(Name = "UnCompiledQuery")]
    public void UnCompiledQuery()
    {
        Func<TestDbContext, Team> unCompileQuery = context =>
        {
            return context.Teams.OrderBy(o => o.Id).FirstOrDefault()!;
        };
        var stopWatch = new Stopwatch();
        teamContext.Database.EnsureDeleted();
        teamContext.Database.EnsureCreated();
        stopWatch.Start();
        for (var i = 0; i < 100; i++)
        {
            var blog = unCompileQuery(teamContext);
        }
        stopWatch.Stop();
        Console.WriteLine("常规查询:" + stopWatch.Elapsed);
    }
}

在这里插入图片描述

类中有两个方法,一个是普通查询,一个是显式编译查询。

5.运行

5.1 常规查询

在这里插入图片描述

5.2 显示编译查询

在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。