成立了WCF,EF性能优化小组已经有一段时间了。我们致力于WCF和EF的性能优化,进行了各种尝试,包括WCF方面:配置WCF传输信息量的最大值,修改WCF的传输协议,配置WCF连接池的最大连接数,修改WCF传输信息的类型,JSON,二进制流,还有WCF数据压缩,分流等等;
EF方面:在查询时 加上asNoTracking()无跟踪查询,关闭延迟加载,配置EF的连接池,最后还想到了EF扩展类。
尽管经过了这么多的尝试,但是最后还是没有从根本上解决系统的性能问题。
为什么经过了这么多的尝试还是不行!?
后来老大的一句话点醒了我们:出现的任何问题都是有原因的,一眼看不到问题出在哪,那就一步一步来, 逐步排除,总会找到问题所在。
对啊,咱们怀疑WCF,EF有问题,但是真的是这样吗?有没有去确认过?仅仅是道听途说就把它们判死刑了吗?
没有真实的数据,是没有权利下定论的!
的确,所做的猜测都应该得到证实,所以我们对项目进行了从下而上的详细排查。
一、找关键点
猜测项目中可能影响性能的几个关键点:EF,WCF,底层EF工具类
二、控制变量逐一测试
随后我们就开始以控制变量法进行了一系列的测试。
① 用SqlManager 执行查询语句:
条件 | 结果 |
---|---|
从4W条数据中分页查询出10条数据 | 0 S |
查询所有:共4W条数据 | 1 S |
② 用原生SQL语句 + WCF传输 :
条件 | 结果 |
---|---|
从4W条数据中分页查询出10条数据 | 0.01 S |
查询所有:共4W条数据 | 3.21 S |
③ 仅用原始EF查询 :
条件 | 结果 |
---|---|
从4W条数据中分页查询出10条数据 | 0.26 S |
查询所有:共4W条数据 | 2.21 S |
④ 用项目封装的EF工具类 + WCF传输 :
条件 | 结果 |
---|---|
从4W条数据中分页查询出10条数据 | 21.31 S |
查询所有:共4W条数据 | 4.84 S |
三、得到分析结果
上面是进行的几组测试和其结果:
由①和②可得出结论,WCF会影响效率,但是不会太大可以接受。
由①和③得出结论:EF的影响也在可接受的范围内。
由②、③、④得出项目封装的EF工具类肯定存在问题,因为分页查询10条数据花费20多秒,太异常了。
缩小范围确定是工具类的问题后,在经过排查,终于发现了问题所在。
Expression<Func<TObject, bool>>与Func<TObject, bool>
工具类中封装的方法,条件参数的类型为Func<TObject, bool>
是委托类型,使用这个类型执行查询时会查询表中的全部数据,加载到内存中然后在一遍遍循环,根据条件进行筛选。而采用Expression<Func<TObject, bool>>
类型作为参数时,会将条件添加到sql语句中一并查询出结果。问题就出在这里。
四、解决问题。
修改之后的查询结果:
条件 | 结果 |
---|---|
从4W条数据中分页查询出10条数据 | 0.28 S |
查询所有:共4W条数据 | 4.84 S |
反思
性能问题终于得以解决,但是通过解决问题的过程,也发现了自身存在的一些问题。
我们一开始就跑偏了,把自己局限住了。就是因为咱们对WCF和EF的理解不深,用的太浅。并且把自己限制在WCF和EF的性能优化上。都不知道是不是他们的问题就开始想法解决问题。导致像无头苍蝇似的乱撞,耗费很长时间还没解决问题。
不过塞翁失马焉知非福,对学习来说也不是没有收获,至少加深了咱们对WCF和EF的理解,扩展了知识面。尤其是发现了EF扩展类,他在大数据量操作上还是很有研究价值的。
经过这次测试发现,对于几十万数据来说,有没有WCF和EF对性能影响都不大。再说了WCF和EF存在了这么多年,这么多人使用,肯定有他们存在的意义。要是这么不堪,早倒闭了。其实数据到百万,千万级别时,WCF才会出现性能瓶颈。这是咱们以后考虑的。
结论
1. 没有什么问题是咱们解决不了的,如果这个问题相对复杂,那么就分治。控制变量,进行逐步的排查。最后肯定会找到问题所在。
2. 一开始不了解可以猜测,但是一定要以实际的数据证明自己的猜测是否是正确的,用数据说话,用事实下结论。