好大一个坑: EF Core 异步读取大字符串字段比同步慢100多倍
这两天遇到一个奇怪的问题,通过 EF/EF Core 查询数据库速度奇慢,先是在传统的 ASP.NET 项目中遇到(用的是EF6.0),后来将该项目迁移至 ASP.NET Core 也是同样的问题(用的是EF Core 2.2.2)。
问题触发的条件是所查询的字段中存储了很大的字符串(有400多万个字符),查询耗时竟然要40s左右(对,是40秒),CPU消耗也很高,2核CPU消耗50%-80%左右,而换成 Dapper 则没这个问题。
通过 EF Core 的 Debug 日志跟踪发现,耗时发生在执行完 DbCommand 与 dispose DbDataReader 之间:
2019-02-23 15:46:27.026 [Information] Executed DbCommand ("4"ms) [Parameters=[""], CommandType='Text', CommandTimeout='30']"
2019-02-23 15:47:06.859 [Debug] A data reader was disposed.
通过日志跟踪信息看,很容易会怀疑耗时可能发生在 ADO.NET DataReader 读取数据时,但这个怀疑与 Dapper 查询正常矛盾,而且 CPU 消耗高也说明耗时不是出现在 IO 层面。
后来在 stackoverflow 上找到了线索 Poor performance when loading entity with large string property using Entity Framework
I had the same issue yesterday. What I did find out is that async operations with Entity Framework is broken or at least very slow. Try using the same operations synchronously
当时看到了这个线索,有点不相信,异步竟然会引起这个问题,不是默认都使用异步吗?只是抱着试试看的心理将代码中的 ToListAsync() 改为 ToList() ,结果却让人大吃一惊,多次测试,查询耗时在 100-500 ms 之间,快了 100 多倍。
更新
触发这个问题有 3 个条件:
1)读取的字符串很大
2)使用 DbCommand.ExecuteReaderAsync 异步方法读取
3)调用 ExecuteReaderAsync 时没有给 behavior 参数传值 CommandBehavior.SequentialAccess
在 Dapper 中没有出现问题是因为 Dapper 中设置了 CommandBehavior.SequentialAccess ,详见 Dapper 的源代码 SqlMapper.Async.cs#L945
using (var reader = await ExecuteReaderWithFlagsFallbackAsync(cmd, wasClosed, CommandBehavior.SequentialAccess | CommandBehavior.SingleResult, command.CancellationToken).ConfigureAwait(false))
{
//...
}
EF Core 中会出现这个问题是因为 EF Core 调用的是 ExecuteReaderAsync(CancellationToken cancellationToken) ,没有设置 CommandBehavior ,详见 EF Core 的源代码 RelationalCommand.cs#L292
result = new RelationalDataReader(
connection,
dbCommand,
await dbCommand.ExecuteReaderAsync(cancellationToken),
commandId,
Logger);
关于 CommandBehavior.SequentialAccess 详见微软官方文档
Provides a way for the DataReader to handle rows that contain columns with large binary values. Rather than loading the entire row, SequentialAccess enables the DataReader to load data as a stream. You can then use the GetBytes or GetChars method to specify a byte location to start the read operation, and a limited buffer size for the data being returned.
好大一个坑: EF Core 异步读取大字符串字段比同步慢100多倍的更多相关文章
- ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK
看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, 加入一个表10W数据,另一个表也是10万数据,当你用linq建立一个连接查询 ...
- ASP.NET MVC + EF 利用存储过程读取大数据
ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK 看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, ...
- net core 小坑杂记之配置文件读取(不定期更新)
其实很早就想写了,原想等积累差不多了再写的,但是发现遇到一个当时记下效果会比较好,所以就不定期更新这个系列了,后面获取会整个整理一下. 此篇记载net core入门时踩的一些坑,网上教程太少了,也不规 ...
- 深入理解 EF Core:EF Core 读取数据时发生了什么?
阅读本文大概需要 11 分钟. 原文:https://bit.ly/2UMiDLb 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能 ...
- .NET 5/.NET Core使用EF Core 5连接MySQL数据库写入/读取数据示例教程
本文首发于<.NET 5/.NET Core使用EF Core 5(Entity Framework Core)连接MySQL数据库写入/读取数据示例教程> 前言 在.NET Core/. ...
- [翻译 EF Core in Action 2.1] 设置一个图书销售网站的场景
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 1.6]你的第一个EF Core应用程序
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- EF Core 3.0 Preview 9 的2个小坑
之前我们的数据库服务器使用的是 SQL Server 2008 R2 ,由于从 EF Core 3.0 Preview 6 开始不支持 UseRowNumberForPaging ,只能停留在 EF ...
- 万字长文,带你彻底理解EF Core5的运行机制,让你成为团队中的EF Core专家
在EF Core 5中,有很多方式可以窥察工作流程中发生的事情,并与该信息进行交互.这些功能点包括日志记录,拦截,事件处理程序和一些超酷的最新出现的调试功能.EF团队甚至从Entity Framewo ...
随机推荐
- (四)Java工程化--Git基础
GIT学习参考:https://git-scm.com/book/zh/v2 常见命令 git init 初始化项目 git add *.java 添加文件到git版本控制(.java后缀的全部文件) ...
- Django ORM中,如何使用Count来关联对象的子集数量
示例models 解决方法 有时候,我们想要获取一个对象关联关系的数量,但是我们不要所有的关联对象,我们只想要符合规则的那些关联对象的数量. 示例models # models.py from dja ...
- jenkins中slave节点连接的两种常用方式
我们在使用jenkins的时候,一般来说肯定是有slave节点的,本来网上也有好多关于jenkins节点配置的教程,我也就不写了.简单说明一下:任务一般是在slave上面运行的.当然不是讲master ...
- php 1转成一
function numToWord($num) { $chiNum = array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九'); $chiUn ...
- selenium之 webdriver与三大浏览器版本映射表(更新至v2.29)
1.chrome浏览器 chromedriver版本 支持的Chrome版本 v2.29 v56-58 v2.28 v55-57 v2.27 v54-56 v2.26 v53-55 v2.25 v53 ...
- 用echarts写的multiple-trees demo
echarts-multiple-trees 预览https://zhangzn3.github.io/echarts-multiple-trees/demo.html //根据数据条数自适应区域大小
- jQuery 第六章 jQuery在Ajax应用
1.本章目标 ajax 2.ajax 异步刷新技术,我们的网页不需要全部刷新,按需实现局部刷新,上线后台的交互 用户体验好 地图,前台验证,表单提交,修改,查询等等 原生的js和ajax packag ...
- Python学习笔记二
---恢复内容开始--- 一. python几种数据类型的比较. 从以下几个方面比较: 1. 是否可变. 不可变类型:变量的值可以发生变化,id也变了,相当于创建了一个新的对象,所以一修改值,id就变 ...
- Postman 安装及使用入门教程(我主要使用接口测试)
1.Postman 安装及使用入门教程(我主要使用接口测试)Postman的English官网:https://www.getpostman.com/chrome插件整理的Postman中文使用教程( ...
- openKM部署二次开发,eclipse环境
1.下载openKM_install_forwin安装包,配置jdk环境,start openKM,访问localhost\OpenKM,用户:okmAdmin 密码:admin.查看是否启动成功.安 ...