这两天遇到一个奇怪的问题,通过 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多倍的更多相关文章

  1. ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK

    看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, 加入一个表10W数据,另一个表也是10万数据,当你用linq建立一个连接查询 ...

  2. ASP.NET MVC + EF 利用存储过程读取大数据

    ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK 看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, ...

  3. net core 小坑杂记之配置文件读取(不定期更新)

    其实很早就想写了,原想等积累差不多了再写的,但是发现遇到一个当时记下效果会比较好,所以就不定期更新这个系列了,后面获取会整个整理一下. 此篇记载net core入门时踩的一些坑,网上教程太少了,也不规 ...

  4. 深入理解 EF Core:EF Core 读取数据时发生了什么?

    阅读本文大概需要 11 分钟. 原文:https://bit.ly/2UMiDLb 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能 ...

  5. .NET 5/.NET Core使用EF Core 5连接MySQL数据库写入/读取数据示例教程

    本文首发于<.NET 5/.NET Core使用EF Core 5(Entity Framework Core)连接MySQL数据库写入/读取数据示例教程> 前言 在.NET Core/. ...

  6. [翻译 EF Core in Action 2.1] 设置一个图书销售网站的场景

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  7. [翻译 EF Core in Action 1.6]你的第一个EF Core应用程序

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  8. EF Core 3.0 Preview 9 的2个小坑

    之前我们的数据库服务器使用的是 SQL Server 2008 R2 ,由于从 EF Core 3.0 Preview 6 开始不支持 UseRowNumberForPaging ,只能停留在 EF ...

  9. 万字长文,带你彻底理解EF Core5的运行机制,让你成为团队中的EF Core专家

    在EF Core 5中,有很多方式可以窥察工作流程中发生的事情,并与该信息进行交互.这些功能点包括日志记录,拦截,事件处理程序和一些超酷的最新出现的调试功能.EF团队甚至从Entity Framewo ...

随机推荐

  1. CSS盒模型(Box Model)

    阅读目录 1. 什么是CSS盒模型 2. IE盒模型和W3C盒模型 3. CSS3属性box-sizing 4. 关于盒模型的使用 在最初接触CSS的时候,对于CSS盒模型的不了解,撞了很多次的南墙呀 ...

  2. 在centos7下安装.net core

    在这里记录下安装的过程: 一开始需要去官网下载centos相关的dotnetcore的sdk 上传到linux,解压,发现需要安装libunwind, 安装libunwind:yum install  ...

  3. web富文本编辑器收集

    1.UEditor 百度的. 优点:插件多,基本满足各种需求,类似贴吧中的回复界面. 缺点:不再维护,文档极少,使用并不普遍,图片只能上传到本地服务器,如果需要上传到其他服务器需要改动源码,较为难办, ...

  4. Linux下安装VMware Tools(使虚拟机支持文件拖拽)

    如图点击虚拟机找到安装VMware Tools选项,点击后会在虚拟机桌面显示一个光盘,双击进入如下页面: 选择压缩包将其复制放入Home中不带中文的文件夹: 打开终端,输入cd命令进入文件夹,将压缩包 ...

  5. javascript中数组的方法

    数组的方法 1.concat():连接两个或多个数组 2.indexOf(arg): ​ 查找数组中的arg元素,如果没有,则返回-1,如果有,则返回该元素的最小下标 ​ lastIndexOf(ar ...

  6. 关于 win10 系统中 Anaconda3 中修改 Jupyter Notebook 默认启动目录

    目标: 修改Anaconda3中自带的Jupyter Notebook默认启动目录. 步骤:     1.提前创建好你想要启动位置文件夹.     2.寻找配置文件,"jupyter_not ...

  7. SonarLint 代码质量管理

    Below are the instructions of how to install and use SonarLint. Install SonarLint Extensions in VS20 ...

  8. 斐波那契求第n项

    摘自  https://blog.csdn.net/lpjishu/article/details/51323116 斐波那契求第n项是常见的算法题 方法1  递归法 //斐波那契 0,1,1,2,3 ...

  9. HTTPS开发(SSL--用Tomcat服务器配置https双向认证)

    准备工作: 1.windows+R  cmd 打开命令窗口 2.输入:cd C:\Program Files\Java\jdk1.7.0_80\bin 进入路径找到keytool工具 为服务器生成证书 ...

  10. Linux基础性笔记

    声明:这是我整理的韩顺平老师的课程,仅供自己参考!!! 给自己的一碗汤:学东西要专一(比较难) 第一节 Linux特点总结: 1. 免费的.开源的. 2. 支持多线程(并发).多用户. 3. 安全性比 ...