一、起因 

个人还是比较喜欢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查询百万级数据的性能测试--单表查询的更多相关文章

  1. EF查询百万级数据的性能测试--多表连接复杂查询

    相关文章:EF查询百万级数据的性能测试--单表查询 一.起因  上次做的是EF百万级数据的单表查询,总结了一下,在200w以下的数据量的情况(Sql Server 2012),EF是可以使用,但是由于 ...

  2. T_SQL查询语句(一): 单表查询

    ############################################ 查询语句--SELECT ########################################## ...

  3. EF查询百万级数据的性能测试

    一.起因  个人还是比较喜欢EF的,毕竟不用写Sql,开发效率高,操作简单,不过总是听人说EF的性能不是很好,也看过别人做的测试,但是看了就以为真的是那样.但是实际上到底是怎么样,说实话我真的不知道. ...

  4. MySQL学习9 - 单表查询

    一.单表查询的语法 二.关键字的执行优先级(重点) 三.单表查询示例 1.where约束 2.group by分组查询 3.聚合函数 4.HAVING过滤 5.order by查询排序 6.limit ...

  5. mysql 数据操作 单表查询 目录

    mysql 数据操作 单表查询 mysql 数据操作 单表查询 简单查询 避免重复DISTINCT mysql 数据操作 单表查询 通过四则运算查询 mysql 数据操作 单表查询 concat()函 ...

  6. Mongo查询百万级数据性能问题及JAVA优化问题

    Mongo查询百万级数据  使用分页  skip和limit 效率会相当慢   那么怎么解决呢  上代码 全部查询数据也会特别慢 Criteria criteria = new Criteria(); ...

  7. Mysql常用表操作 | 单表查询

    160905 常用表操作 1. mysql -u root -p 回车 输入密码   2. 显示数据库列表 show databases     3. 进入某数据库 use database data ...

  8. 【T-SQL基础】01.单表查询-几道sql查询题

    概述: 本系列[T-SQL基础]主要是针对T-SQL基础的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础 ...

  9. python实现简易数据库之二——单表查询和top N实现

    上一篇中,介绍了我们的存储和索引建立过程,这篇将介绍SQL查询.单表查询和TOPN实现. 一.SQL解析 正规的sql解析是用语法分析器,但是我找了好久,只知道可以用YACC.BISON等,sqlit ...

随机推荐

  1. MiUI开发者版刷入xposed框架--简洁方法

    一,首先要确定手机是否解锁 可以去这里查看怎么解锁: http://www.miui.com/unlock/index.html 二,手机系统需要是开发者版,且在安全中心的授权管理打开了ROOT授权 ...

  2. python类的内置方法

    1,__init__(self) 初始化方法,实例化一个对象的时候就会被执行 2,__call__(self,*args) 把实例对象作为函数调用,即实例化一个对象后,在对象后面加括号即可调用__ca ...

  3. xp_readerrorlog与sp_readerrorlog

    SQL SERVER 可以使用xp_readerrorlog 或者sp_readerrorlog来查看错误日志. xp_readerrorlog 一共有七个参数: 1. 存档编号 2. 日志类型(1为 ...

  4. UNIX高级环境编程(10)进程控制(Process Control)- 竞态条件,exec函数,解释器文件和system函数

    本篇主要介绍一下几个内容: 竞态条件(race condition) exec系函数 解释器文件    1 竞态条件(Race Condition) 竞态条件:当多个进程共同操作一个数据,并且结果依赖 ...

  5. 1001.A+B Format(10)

    1001.A+B Format(20) github链接:[example link](https://github.com/wgc12/object-oriented 1.对题目的理解: 首先这道题 ...

  6. Python返回数组(List)长度的方法

    其实很简单,用len函数: >>> array = [0,1,2,3,4,5]>>> print len(array) 同样,要获取一字符串的长度,也是用这个len ...

  7. postgresql----几何类型和函数

    postgresql支持的几何类型如下表: 名字 存储空间 描述 表现形式 point 16字节 平面上的点 (x,y) line 32字节 直线 {A,B,C} lseg 32字节 线段 ((x1, ...

  8. ArcGIS js api 手动构建FeatureLayer

    坐标系 var spatialReference = new SpatialReference(4326);1要素坐标点 var pointArr = [ new Point(116.94431351 ...

  9. centos6.5 64位静默安装oracle 10G R2

    操作系统:CentOS release 6.5 (Final) 64位 oracle版本:Oracle Database 10g Enterprise Edition Release 10.2.0.1 ...

  10. SQL操作语句

    SQL语句与Mysql的语句大体上比较相似.以下是sql server的一套练习题,是很好的数据库操作语句学习资料,学校的学习资料,在此整理了以下. 数据库exam:这是一个模拟电子商务,网上直销的数 ...