.NET 性能—Entity Framework Core调优

本文详细介绍了在.NETCoreWeb项目中,针对EFCore框架进行性能优化的策略,包括缓存、主键查询、避免索引失效、指定列查询、分页、一次性查询、关闭跟踪、异步操作以及关联查询的懒加载和自定义SQL等方法。
摘要由CSDN通过智能技术生成

前言

在实际开发过程中,我们遇到性能问题,常见的性能提升方案整体分为硬件、软件、网络三个方面。

按下硬件、网络不提,我们单表从程序层面对系统的性能进行优化,翻来覆去无外乎三个方面

缓存
异步
sql
本片文章,我们针对.NET Core Web项目的EF Core框架进行性能优化。

正文

1、EF Core框架已经本地缓存机制memorycache,所以我们访问一个接口,二次访问的性能相比首次会提升一大截

2、尽可能的通过主键查询

3、在进行字符串模糊查询时,分为三种情况 ‍

‍//StartsWith,相当于sql语句的like ‘A%’

varresult= ProductContext.Products.Where(p => p.ProductName.StartsWith( “A”)).ToList;

//EndsWith,相当于sql语句的like ‘%A’

varresult= ProductContext.Products.Where(p => p.ProductName.EndsWith( “A”)).ToList;

//Contains,相当于sql语句的like ‘%A%’

varresult= ProductContext.Products.Where(p => p.ProductName.Contains( “A”)).ToList;

其中的Contains会导致索引失效,不建议使用

4、指定列查询。即字段查询、传输需要时间,字段越多,所需的时间就越多,所以我们可以指定我们所需的字段

ProductContext.Products.Select(p => new{ p.ProductId, p.ProductName})

对应的sql为:

selectProductId,ProductName

fromProducts

5、分页查询(常用于客户端查询)

intpageIndex = 1;

intpageSize = 10;

varresult= ProductContext.Products

.Where(p => p.ProductName.StartsWith( “A”))

.Take(pageSize) // 限制结果集数量。

.Skip((pageIndex - 1) * pageSize) // 数据的偏移量

.ToList;

6、一次性查询数据量较多时(如导出报表),借助缓冲区处理,即直接ToList、ToArray

ps:某些时候使用缓冲区而不是缓存,是因为缓冲区使用时会清空,而缓存不到过期时间不自动清空,某些场景下会浪费内存空间

//默认流式处理,遍历使用result时每次循环都会查询数据库

varresult= ProductContext.Products.Where(p => p.ProductName.StartsWith( “A”));

//缓冲区处理(一次性将数据查出,使用result时,直接从队列中取数据)

varresult= ProductContext.Products.Where(p => p.ProductName.StartsWith( “A”)).ToList;

7、EF Core会对查询出来的数据进行缓存、跟踪。跟踪监控造成额外的空间浪费,但能方便更新数据,所以在不涉及修改的情况下(只查询时),我们可以用AsNoTracking方法来手动关闭跟踪

varresult= ProductContext.Products

.Where(p => p.ProductName.StartsWith( “A”))

.AsNoTracking

.ToList;

8、使用异步 ToListAsync

以上为单个表数据的EF Core优化

那么如果是多个表的数据查询如何优化呢?即涉及关联查询的情况

9、懒加载Include,关联查询一次性加载

//主表为product表,副表为产品变更日志表productLogs

varresult= ProductContext.Product.Include(p=> p.productLogs).ToList;

这里会存在笛卡尔积的问题,即副表关联数据为null时(假设某产品没有变更记录),也会查询副表,如果副表null数据较多时,会造成性能下降。

那么我们可以通过拆分查询AsSplitQuery 解决这个问题

varresult= ProductContext.Product.Include(p=> p.productLogs).AsSplitQuery.ToList;

原理

默认预先加载(懒加载)时,EF core为我们生成的sql语句为left join语句,查询结果为主表、副表的所有字段;右表数据的字段会存在null。

数据库查询进行笛卡尔积查询,实际查询了4次

拆分查询时,EF Core会生成两个sql语句:

1、单表查询主表product

2、主表product与副表productLogs进行inner join,查询结果为副表的所有字段

实际查询了2次

所以会提升性能

10、自定义sql语句。即不使用EF Core本身生成的sql

varresult= ProductContext.Product.FromSqlRaw( “select * from product”).ToList;

本方法也可以用于大数据量更新。 ‍

转自:隐人语

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值