EF查询百万级数据的性能测试
一、起因
个人还是比较喜欢EF的,毕竟不用写Sql,开发效率高,操作简单,不过总是听人说EF的性能不是很好,也看过别人做的测试,但是看了就以为真的是那样。但是实际上到底是怎么样,说实话我真的不知道。我只知道选什么的框架是基于实际情况的,博主在一个创业公司上班,选的就是EF框架,刚做了一个项目,数据也就几万不到,感觉性能没那么差劲。于是,就想多弄点数据测试一下。再说一遍,本着 求真务实的方针,是针对现实中的业务需求来测试的,不是来单比性能的。你要是做个ERP系统,都去考虑千万级并发的架构,那当我没说。毕竟不是基于实际项目的框架选择都是耍流氓。
二、声明
基于实际的项目,考虑到博主一般的遇到的上线项目对于数据的增删改操作时,操作的数据一般都是一个,两个,多了有十几个,对于一下同时提交几十个数据进行增删改的,原谅博主还没有见过,更有甚者,提交几百个数据进行增删改,博主想也是没有想过。但是在这个数量级下的增删改操作,我相信EF还是能够胜任的,所以本文不再测试EF的增删改性能,因为感觉完全能够满足一般项目的需要。本文只测试EF的单表查询功能,之后有时间会做复杂的链接查询的测试。
三、测试条件


老百姓的配置,自己的工作电脑。
Sql Server 2012,Entity Framework 6.1.3。
四、测试数据
鉴于以前看过的测试都是两三个字段,且数据过于简单,以防有这方面的影响,又因为实际项目中的字段可能较多,而且数据量也比较复杂,就模拟了一个较为接近的数据表,再说一遍,本着求真务实的革命主义方针,针对现实的项目来测试。

数据量100W:

五、开始测试
做了一个WinForm的测试,界面如下:

1.进行Find测试,随机生成id,左边显示查询用时,先上代码。
private PortalContext db = new PortalContext();
private int count = ;
private TimeSpan ts = new TimeSpan();
private void btnFind_Click(object sender, EventArgs e)
{ count++;
Random r = new Random();
var id = r.Next(, );
txtId.Text = id.ToString(); Stopwatch sw = new Stopwatch();
sw.Start();
var user = db.Users.Find(id);
sw.Stop(); txtUserInfo.Text = UserToString(user);
ts += sw.Elapsed;
string time = sw.Elapsed + "(" + sw.Elapsed.Seconds + "s" + sw.Elapsed.Milliseconds + "ms)";
txtDisplay.AppendText("Find查询id(" + id + ")用时:" + time + Environment.NewLine);
txtData.Text = "执行" + count + "次,平均耗时" + new TimeSpan((ts.Ticks / count));
}
结果如下:

可以看出,在100w数据的情况下,利用Find根据主键id查询根本无压力,至于第一次很长时间,应该是连接数据花费了一些时间。
2.进行Where测试,代码如下。
private void btnWhere_Click(object sender, EventArgs e)
{ bool[] valids = new bool[] { false, true };
string[] works = new[] { "程序猿", "攻城狮", "产品汪", "键盘侠", "代码狗" };
UserType[] userTypes = new[] { UserType.合作方, UserType.普通用户, UserType.律师 };
Random r = new Random(); int num = r.Next(, );
int num2 = r.Next(, ); int max = Math.Max(num, num2);
int min = Math.Min(num, num2); bool isValid = valids[num % ];
string work = works[num % ];
UserType type = userTypes[num % ]; txtIsValid.Text = isValid.ToString();
txtWork.Text = work;
txtUserType.Text = type.ToString();
txtAmountMin.Text = min.ToString();
txtAmountMax.Text = max.ToString(); Stopwatch sw = new Stopwatch();
sw.Start();
var query = db.Users.Where(u => true);
var queryWhere = query.Where(u =>u.UserType == type &&u.IsValid == isValid && u.Work == work && (u.Amount >= min && u.Amount <= max)).Take();
var list = queryWhere.ToList();
sw.Stop(); labelWhere.Text = string.Format("where(u=> u.UserType=={0} && u.IsValid =={1} && u.Work == {2} u.Amount >= {3} && u.Amount <={4}).Take(1000)",
type,isValid,work, min, max); string time = sw.Elapsed + "(" + sw.Elapsed.Seconds + "s" + sw.Elapsed.Milliseconds + "ms)";
txtDisplay.AppendText("Where查询到"+list.Count()+"条数据,用时:" + time + Environment.NewLine); }
在这里用Where获取了前1000条数据,实际项目中基本不可能这样来,或者全部ToList()出来,考虑到项目中有些情况下确实需要全部ToList()出来一些数据,但是取1000条应该足够了,对于其他情况下来讲,这项测试没有太大的意义,我们等会看分页的性能。

附上一些全部ToList()出来时的测试:

当然实际是不可能这样玩的,也就看看,看了一下内存,3w多条数据也就30M左右。
附:Where查询的一些优化,其实这个之前是知道的,忘了往上贴了,谢谢@搵中求胜 博友的提醒,再次接着机会又测试了一下。
1.200w的数据(数据大才能体现出来效果),在没有AsNoTracking的情况下

2.加上了AsNoTracking(),一般我们的查询基本上不用跟踪只要数据就行了。可以看出来性能明显提高,同样的数据,将近提高了一般的性能。
var query = db.Users.AsNoTracking().Where(u => true);
var queryWhere = query.Where(u =>u.UserType == type &&u.IsValid == isValid && u.Work == work && (u.Amount >= min && u.Amount <= max));

3.还有,许多情况下我们不需要全部的数据,直接先用Select()选出来一些需要的字段,也会提高不少性能。
var query = db.Users.AsNoTracking().Where(u => true);
var queryWhere = query.Where(u =>u.UserType == type &&u.IsValid == isValid && u.Work == work && (u.Amount >= min && u.Amount <= max))
.Select(u=>new
{
u.Id,
u.UserName
});
var list = queryWhere.ToList();

3.Any,First ,Count的测试
代码都基本一样,这里只附上一些图片参考。



上边的都能查询存在不存在,但是相比来说,Any,First 对于存在的情况下,性能很好,而count对于不存在时性能却很好,我也不知道为什么的。感觉有时候真的可以用Count查询存在不存在的,毕竟平均效果好。PS:以前看一篇文章说Count比Any差了不知道多少倍,查询存在不存在推荐用Any。现在看来,也差不多啊。
4.分页查询。
从实际项目来看,用户在看分页数据时,一般都是翻看前10页左右,而且每页的数据量也大概在10-30个之间,太多了没必要。所有分页的pageIndex和pageSize都设置在了这些数据之间,可能页码的大小pageIndex,pageSize过大的时候也会影响性能,这个我们随后再加以测试。

200ms左右吧,基本还说的过去,可能是在排序的问题上花费了太多的时间。
附上一张pageIndex比较大的测试结果(pageIndex在800-1000之间),果然页码比较大的时候花费时间变长了,pageSize就不用说了,肯定时间也会变长。

5.Contains查询
这里代码稍微做了改动,感觉也跟这个没关系
private void btnContains_Click(object sender, EventArgs e)
{
string[] usernames = new[] { "zhao", "wang", "li", "san", "zhaoliu" };
bool[] valids = new bool[] { false, true };
string[] works = new[] { "序猿", "攻城", "产品汪", "盘侠", "代码" };
....
//全名称改成了部分名称,能保证是模糊查询吧。。[笑]
}

感觉确实有点慢,500ms左右,毕竟Contains,毕竟like,毕竟100w数据吧,有些条件下还是可以接受的,毕竟方便,做个自己用的查询还是可以的。
六、数据量加大
既然是百万级别,也不能只有一百万。
1.二百万的数据






总结一下:
Find无压力,没区别,大概是因为主键索引的缘故。
Any,First,Count都还在100ms左右,还能用。
分页已经到了400ms,感觉已经不能接受了。但是我真的还没咋见过能分几千页的,这里可以先用Where过滤到一些老旧数据或者不要的数据再进行分页应该还是不错的。
Contains已经到了1s了,这对于用户来说已经不能接受了,但是到了这个级别的数据,应该就用上检索引擎了。这个就不考虑了。
2.三百万的数据







总结一下:
Find无压力,还是没啥区别,大概是因为主键索引的缘故。
Any,First能查询到结果时还是挺快了,Count感觉在这里更好用了。
分页到了500ms,还是那句话,这里可以先用Where过滤到一些老旧数据或者不要的数据再进行分页,可以看一下,分页的总记录数都是一,二百万,算了自己想办法优化吧。
Contains不说了。
4.四百万的数据







总结一下:
Find无压力,还是没啥区别,大概是因为主键索引的缘故。
Any,First查不到就慢了,Count感觉在这里更好用了。
分页不说了。
Contains不说了。
七、结语
当写到这里的时候,我感觉我错了,这些好像和EF没有半毛钱关系,这么简单的查询,EF生成Sql语句应该不耗费什么时间。根本没有发挥出EF的linq语法什么的,各种复杂查询语句,各种连接语句的生成。纳尼!!!
但是既然都到这个地步了,那就算了,就当做是对Sql Server性能的考验吧。话说应该200w数据的情况下,EF应该还是可以随便这样用的,再说了,我的用的是自己的个人电脑,要是用服务器肯定无压力的。
感觉EF快不快还是和程序员写的语句有关吧,怎么获取数据,怎么查询,怎么拼接,毕竟到最后都是生成sql语句去查询,所以瓶颈应该在如何快速的生成高效的Sql语句。
对于一个创业公司,刚开始做的项目,数据连几十万都不到,肯定果断用EF啊,容易上手,开发方便,不用写Sql是最重要的,毕竟微软的东西,都迭代这么多版本了,应该优化的差不多了吧。
PS:第一次写博客,不知道测试的姿势对不对,方向对不对,有错了大神指出来,请不要喷我,我会哭的[哈哈],我只是一个只会写增删改查的小码农。
EF查询百万级数据的性能测试的更多相关文章
- EF查询百万级数据的性能测试--多表连接复杂查询
相关文章:EF查询百万级数据的性能测试--单表查询 一.起因 上次做的是EF百万级数据的单表查询,总结了一下,在200w以下的数据量的情况(Sql Server 2012),EF是可以使用,但是由于 ...
- EF查询百万级数据的性能测试--单表查询
一.起因 个人还是比较喜欢EF的,毕竟不用写Sql,开发效率高,操作简单,不过总是听人说EF的性能不是很好,也看过别人做的测试,但是看了就以为真的是那样.但是实际上到底是怎么样,说实话我真的不知道. ...
- Mongo查询百万级数据性能问题及JAVA优化问题
Mongo查询百万级数据 使用分页 skip和limit 效率会相当慢 那么怎么解决呢 上代码 全部查询数据也会特别慢 Criteria criteria = new Criteria(); ...
- Sql Server分页分段查询百万级数据四种项目实例
实际项目中需要实现自定义分页,最关键第一步就是写分页SQL语句,要求语句效率要高. 那么本文的一个查询示例是查询第100000-100050条记录,即每页50条的结果集.查询的表名为infoTab,且 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(37)-文章发布系统④-百万级数据和千万级数据简单测试
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(37)-文章发布系统④-百万级数据和千万级数据简单测试 系列目录 我想测试EF在一百万条数据下的显示时间! ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(37)-文章发布系统④-百万级数据和千万级数据简单测试
系列目录 我想测试EF在一百万条数据下的显示时间!这分数据应该有很多同学想要,看看EF的性能! 服务器 现在来向SQL2008R2插入1000000条数据吧 declare @i int; ; beg ...
- poi实现百万级数据导出
注意使用 SXSSFWorkbook 此类在构造表格和处理行高的时候效率极高,刚开始时我使用的 XSSFWorkbook 就出现构造表格效率极低,一万行基本需要3秒左右,那当导出百万级数据就慢的要死啦 ...
- Sql Server中百万级数据的查询优化
原文:Sql Server中百万级数据的查询优化 万级别的数据真的算不上什么大数据,但是这个档的数据确实考核了普通的查询语句的性能,不同的书写方法有着千差万别的性能,都在这个级别中显现出来了,它不仅考 ...
- 实战手记:让百万级数据瞬间导入SQL Server
想必每个DBA都喜欢挑战数据导入时间,用时越短工作效率越高,也充分的能够证明自己的实力.实际工作中有时候需要把大量数据导入数据库,然后用于各种程序计算,本文将向大家推荐一个挑战4秒极限让百万级数据瞬间 ...
随机推荐
- Java Class Loader
Reference: [1] http://www.cnblogs.com/kevin2chen/p/6714214.html 当调用 java命令运行一个java程序时,会启动一个java虚拟机进程 ...
- linux开发常用命令
最近经常查看服务器上的log文件,有时log文件太大查起来很不方便,看了看网上说可以部分查询,就先记录一下吧 Linux中查看部分文件内容命令head,tail,sed的用法: Linux中的查看文件 ...
- Spring-bean作用域scope详解
Spring Framework支持五种作用域(其中有三种只能用在基于web的Spring ApplicationContext). singleton 在每个Spring IoC容器中一个bean定 ...
- 你真的了解WebSocket吗?
WebSocket协议是基于TCP的一种新的协议.WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符.它实现了浏览器与服务器全双工(full-duplex ...
- 纯css实现多标签浮动居中(任意个数)
在做的一个网页上有一块要用浮动标签,具体就是网页底部有未知数量,未知尺寸的元素要水平居中,有点类似于分页器. 首先,我们先新建一个容器con,就是标签的爸爸,用来控制标签在页面的位置,.father{ ...
- SparkR安装部署及数据分析实例
1. SparkR的安装配置 1.1. R与Rstudio的安装 1.1.1. R的安装 我们的工作环境都是在Ubuntu下操作的,所以只介绍Ubuntu下安装R的方法 ...
- cuda学习3-共享内存和同步
为什么要使用共享内存呢,因为共享内存的访问速度快.这是首先要明确的,下面详细研究. cuda程序中的内存使用分为主机内存(host memory) 和 设备内存(device memory),我们在这 ...
- 分布式锁2 Java非常用技术方案探讨之ZooKeeper
前言: 由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.以自己结合实际工作中的一些经验和网上看到的一些资料 ...
- CSS小技巧-怎样让每行多余的文字显示文省略号?
1.white-space:nowrap 如果是中文,则需要设置行末不断行 2.overflow:hidden 设置超出控件范围隐藏 3.text-overflow:ellipsis
- poj3417
poj3417 题意 给出一颗 n 个节点, n - 1 条边的树,再加上 m 条新边,允许删掉树边和新边各一条,问能使树分为两部分的方案数. 分析 在树的基础上加上不重复的新边一定会构成环,那么考虑 ...