第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题
一. 开篇说明
EF的性能问题一直以来经常被人所吐槽,究其原因在于“复杂的操作在生成SQL阶段耗时长,且执行效率不高”,但并不是没有办法解决,从EF本身举几个简单的优化例子:
①:如果仅是查询数据,并不对数据进行增、删、改操作,查询数据的时候可以取消状态追踪。
db.TestInfor.AsNoTracking().FirstOrDefault();
②:用什么查什么,比如一张表有100多个字段,本次业务只需要5个字段,一定是select这5个字段,然后toList,而不是全部查询,再toList()
③:利用EF调用原生SQL语句或者EF调用存储过程执行。 (目前为止,没有发现该方式存在什么问题,而且性能也很快,广大博友如果认为这种方式存在什么问题,可以留言给我普及扫盲一下)
以上的几种方式,或许在一定程度上能解决一些问题,但面对大数据量的增、删、改,还是心有力而力不足。
1. 前面的章节
前面的章节提到了Z.EntityFramework.Extensions插件解决EF性能问题,该插件确实很nb,性能很高,而且功能很全,但是呵呵,天上没有掉馅饼的好事,该插件是收费的,如果你公司不差钱,或者你是土豪,那么强烈推荐使用该插件,性能确实不错,并且你可以直接右上角 x,不需要看该篇文章了^_^。
但往往现实是残酷,穷人居多,这个时候就需要找免费的解决方案了,前面章节提到了 SqlBulkCopy 类(与EF没有半毛钱关系),它可以实现增加操作,不得不说,它在处理大数据量的增加的时候,确实很出色!!!。
那么删除和更新怎么办呢?
答案是:可以借助 Z.EntityFrameWork.Plus.EF6 才解决。
2. 进入主题
Z.EntityFrameWork.Plus.EF6 和 Z.EntityFramework.Extensions 是同一公司的产物,该插件支持的功能很多,比如 删除、更新、缓存机制、过滤器等等,但唯独没有新增操作(都懂得,什么功能都有的话,他的兄弟 Z.EntityFramework.Extensions 怎么办?)。
本章节仅介绍删除和更新两个最常用的功能。
该插件的几点说明:
①:仅支持EF5、EF6、EF Core,注意不同的版本对应该插件的后缀不同,该章节使用的是EF 6.2,所以对应 Z.EntityFrameWork.Plus.EF6
②:官方号称:Improve EF Performance by 2000%
③:可以通过Nuget进行安装
④:文档地址 : http://entityframework-plus.net/batch-delete
GitHub地址: https://github.com/zzzprojects/EntityFramework-Plus
3. 数据库准备

二. 删除相关
1. Delete() 同步删除方法
2. DeleteAsync() 异步删除方法 <根据实际业务场景选择使用>
3. BatchSize:批次大小
Delete和DeleteAsync两个删除方法都可以设置该参数的值:x => x.BatchSize,该参数表示一次执行的条数,默认值为4000,比如你要删除4w条数据,默认值的话,就要删除10次,
适当的提高该值,会增加删除效率,但并不代表无限增大。
特别注意:下面测试使用的Delete方法是默认块级大小4000的情况下进行测试,后面把BatchSize直接改为8w,删除8w条数据在1.6s左右
4:BatchDelayInterval:批次执行的时间间隔
比如BatchSize=4000,BatchDelayInterval=1000,删除4w条数据,表示的意思是删除4000的时候等待1s,然后再删除。
PS:该参数不是很常用,适用于你既需要删除很多数据,而且在批处理之间的暂停间隔继续执行CRUD操作
5:Executing:执行删除命令之前,去执行一段命令文本
PS:根据实际场景选择使用。
下面进行性能测试:(1w条、 4w条、 8w条数据的删除操作)
(1). EF原生删除代码
/// <summary>
/// EF普通方法测试性能
/// </summary>
/// <param name="db"></param>
public static void DeleteCommon1(DbContext db)
{
Console.WriteLine("---------------------调用普通方法1删除--------------------------------");
var list=db.Set<TestTwo>.Where(u=>u.id!="1").ToList();
9 Stopwatch watch = Stopwatch.StartNew();
foreach (var item in list)
{
db.Entry(item).State = EntityState.Deleted;
}
int count = db.SaveChanges();
watch.Stop();
Console.WriteLine($"{count}条数据耗时:{watch.ElapsedMilliseconds}");
}
(2). EF调用SQL语句的代码
/// <summary>
/// EF调用SQL语句测试删除
/// </summary>
/// <param name="db"></param>
public static async void DeleteCommon2(DbContext db)
{
Stopwatch watch = Stopwatch.StartNew();
string sql = "delete from TestTwo where id !='1' ";
int count = ;
//加上await,表示在这一步上异步方法执行完
var response = await db.Database.ExecuteSqlCommandAsync(sql);
count = response;
Console.WriteLine("异步方法已经开始执行,请耐心等待");
watch.Stop();
Console.WriteLine($"{count}条数据耗时:{watch.ElapsedMilliseconds}");
}
(3). 利用该插件扩展的代码
public static void DeletePlus(DbContext db)
{
Console.WriteLine("---------------------调用扩展方法删除--------------------------------");
Stopwatch watch = Stopwatch.StartNew();
int count = db.Set<TestTwo>().Where(u => u.id != "").Delete();
//设置块级大小(默认4000)
//int count = db.Set<TestTwo>().Where(u => u.id != "1").Delete(u => u.BatchSize = 80000);
watch.Stop();
Console.WriteLine($"{count}条数据耗时:{watch.ElapsedMilliseconds}");
}
最终的测试结论(下面的时间是取三次结果的平均值):
1w条数据 4w条数据 8w条数据
EF原生删除 76s 累哭了 累哭了
EF调SQL语句 1.152s 1.232s 1.558s
Z.Plus(默认块) 1.307s 1.982s 2.675s
最终结论: Z.EntityFrameWork.Plus.EF6的删除比EF原生要快的多! 但EF直接调用SQL语句貌似更快哈。
三. 更新相关
有了上面删除的基础,这里的更新操作就容易的多,更新的性能提升与删除类似,这里不再单独测试了,下面简单粗暴,直接介绍用法。
1. Update() 同步更新方法
2. UpdateAsync() 异步更新方法
3. Executing:上述两个方法的一个参数,表示执行更新命令之前,去执行一段命令文本(根据实际情况选择使用)
直接上代码:
public static void UpdatePlus(DbContext db)
{
Console.WriteLine("---------------------调用扩展方法更新--------------------------------");
Stopwatch watch = Stopwatch.StartNew();
int count = db.Set<TestTwo>().Where(u => u.id != "").Update(x => new TestTwo()
{
t21 = "",
t22 = ""
});
watch.Stop();
Console.WriteLine($"{count}条数据耗时:{watch.ElapsedMilliseconds}");
}
综述:该插件的使用非常简单,在使用上,可以说没有任何难度可言,很多情况下,并不是你不会解决,而是你缺少一双善于发现的眼镜。
免费的大数据解决方案: SqlBulkCopy + Z.EntityFrameWork.Plus + EF调用SQL语句/存储过程 或许是一个不错的选择。
如果你对EF感兴趣,可以关注该章节:ORM系列之Entity FrameWork详解(持续更新)
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,如需代码请留下你的评论,加我QQ:604649488 (备注:评论的博客名)
第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题的更多相关文章
- 第九节: EF的性能篇(二) 之 Z.EntityFramework.Extensions程序集解决EF的性能问题
一. 综述 该模块主要介绍:EF的性能优化插件Z.EntityFramework.Extensions,该插件收费. (一). 简介 1. 相关网站:http://www.zzzprojects.co ...
- centos LNMP第一部分环境搭建 LAMP LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/php/{p.conf.default,p.conf} php运行方式SAPI介绍 第二十三节课
centos LNMP第一部分环境搭建 LAMP安装先后顺序 LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/local/php/{ ...
- (转)第二十三节 inotify事件监控工具
第二十三节 inotify事件监控工具 标签(空格分隔): Linux实战教学笔记-陈思齐 原文:http://www.cnblogs.com/chensiqiqi/p/6542268.html 第1 ...
- 风炫安全WEB安全学习第二十三节课 利用XSS获取COOKIE
风炫安全WEB安全学习第二十三节课 利用XSS获取COOKIE XSS如何利用 获取COOKIE 我们使用pikachu写的pkxss后台 使用方法: <img src="http:/ ...
- 【php增删改查实例】第二十三节 - PHP文件上传
22. PHP文件上传 22.1 资源文件 将这三个东西拷贝项目的根目录. 拷贝完毕后,打开upload.html: 现在,我们在项目的根目录去编写一个upload.php. PHP给我们提供了很多关 ...
- 第二百一十三节,jQuery EasyUI,NumberBox(数值输入框)组件
jQuery EasyUI,NumberBox(数值输入框)组件 功能:只能输入数值,和各种数值的计算 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI ...
- [ExtJS5学习笔记]第二十三节 Extjs5中表格gridpanel的列格式设置
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39665979 官方文档:http://docs.sencha.com/extjs/5. ...
- 第二十三节:Java语言基础-详细讲解函数与数组
函数 函数在Java中称为方法,在其他语言中可能称为函数,函数,方法就是定义在类中具有特定功能的程序.函数,在Java中可称为方法. 函数的格式: 修饰符 返回值类型 函数名(参数类型 参数1, 参数 ...
- python第二十九天-----继续学习第三模块——前几天旅行去了
subprocess模块 import subprocess subprocess.getstatusoutput('dir')#接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结 ...
随机推荐
- 5.1Python数据处理篇之Sympy系列(一)---Sympy的大体认识
目录 目录 前言 目录 前言 sympy是python一个强大的数学符号运算第三方库,具体的功能请看下面操作 官网教程: https://docs.sympy.org/latest/tutorial/ ...
- web渗透 学习计划(转载)
作者:向生李链接:https://www.zhihu.com/question/21914899/answer/39344435来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 【Python 22】52周存钱挑战2.0(列表list和math函数)
1.案例描述 按照52周存钱法,存钱人必须在一年52周内,每周递存10元.例如,第一周存10元,第二周存20元,第三周存30元,直到第52周存520元. 记录52周后能存多少钱?即10+20+30+. ...
- linux 本机内核模块
make -C /lib/modules/4.13.0-36-generic/build M=/$(pwd) modules 内核里只需要写obj-m:=hello.o
- Spark1.6之后为何使用Netty通信框架替代Akka
解决方案: 一直以来,基于Akka实现的RPC通信框架是Spark引以为豪的主要特性,也是与Hadoop等分布式计算框架对比过程中一大亮点. 但是时代和技术都在演化,从Spark1.3.1版本开始,为 ...
- JavaScript的函数闭包详细解释
闭包是指有权访问另一个函数作用域中的变量的函数 一.创建闭包的常见的方式: 就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量. //通过闭包可以返回局部变量 function b ...
- sql server 压缩数据库
收缩日志 ALTER DATABASE 数据库名称 SET RECOVERY SIMPLEDBCC SHRINKDATABASE(数据库名称, 0) 压缩数据库ALTER DATABASE 数据库名称 ...
- 纯代码系列:Python实现验证码图片(PIL库经典用法用法,爬虫12306思路)
现在的网页中,为了防止机器人提交表单,图片验证码是很常见的应对手段之一.这里就不详细介绍了,相信大家都遇到过. 现在就给出用Python的PIL库实现验证码图片的代码.代码中有详细注释. #!/usr ...
- Kafka 详解(二)------集群搭建
这里通过 VMware ,我们安装了三台虚拟机,用来搭建 kafka集群,虚拟机网络地址如下: hostname ipaddress ...
- PyInstaller Extractor安装和使用方法
PyInstaller Extractor是可以提取出PyInstaller所创建的windows可执行文件的资源内容. 关于PyInstaller的介绍:PyInstaller安装使用方法 使用Py ...