EF性能分析(一):动态SQL性能差.从OrderBy开始分析
1. 问题背景
在我的力推下,部门业务开发转向ABP,其中ORM采用的是EntityFrameworkCore.
然而,在数据查询方面,出现了重大的性能问题...
请看代码:
//在一个百万数据量的表中分页获取十条数据居然花了180ms左右,简直不能忍。
var entityList = await query
.PageBy(input)
//这是个字符串:MonthCode desc
.OrderBy(input.Sorting)
.ToListAsync();
这是很常见的Abp示例项目中的CURD中的常规代码,被大量使用...
2.分析问题
2.1 遇到问题先猜,提高查问题效率
开始我平淡的猜测...
a. 整段代码平淡无奇,【但是OrderBy的出现】直接解决了任意字段排序的问题,简直解放双手,要知道百万数据在前端排序是不可能的。
b. 【问题只能被转移,不能被消灭】 --我的编程思想
c. 所以,问题初步定在Orderby上。
2.2 猜到问题代码,继续猜可能的原因
a. 按下F12查看函数签名:
OrderBy(this IQueryable source, ParsingConfig config, string ordering, params object[] args);
b. 开始感性的猜测,只需要一路F12即可。
1. IOderQueryable继承自IQueryable
2. IQueryable由:Type(类型),Expression(表达式树),Provider(表达式树的解析器)组成
3. Expression的构建需要涉及到元数据反射创建。
4. 反射!!!元数据!!!所以真相可能是:从SQL字符串,动态生成Expression!然后,创建IOrderQueryable,最后由EF的Provider解析出SQL,而不是简单的直接作为Orderby字符串拼接...
2.3 猜个大概了,开始证明它吧!
2.3.1 查看OrderBy源码
我用ILSpy反编译工具
public static IOrderedQueryable OrderBy(this IQueryable source, ParsingConfig config, string ordering, params object[] args)
{
Check.NotNull<IQueryable>(source, "source");
Check.NotEmpty(ordering, "ordering");
ParameterExpression[] parameters = new ParameterExpression[]
{
ParameterExpressionHelper.CreateParameterExpression(source.ElementType, string.Empty)
};
//果真String转Expression,还没有缓存,是快不起来了...
IEnumerable<DynamicOrdering> arg_48_0 = new ExpressionParser(parameters, ordering, args, config).ParseOrdering(false);
Expression expression = source.Expression;
foreach (DynamicOrdering current in arg_48_0)
{
expression = Expression.Call(typeof(Queryable), current.MethodName, new Type[]
{
source.ElementType,
current.Selector.Type
}, new Expression[]
{
expression,
Expression.Quote(Expression.Lambda(current.Selector, parameters))
});
}
Expression expression2 = DynamicQueryableExtensions.OptimizeExpression(expression);
return (IOrderedQueryable)source.Provider.CreateQuery(expression2);
}
2.3.2 初步结论:
为什么是初步结论呢,,,因为EF还有个二次缓存机制不是...热启动怎么也这么慢,是不是得查它
所以:OrderBy的时候,是由字符串,反射生成表达式树后,创建Queryable,交给EF做后续处理!所以,性能是快不起来的,这里性能大概就消耗了80ms左右!
2.3.3 开始查EntityFramework的缓存机制
其实这个阶段不用查...因为OrderBy每次都会执行生成Expression的过程,所以性能稳稳有问题,但是我真的好奇...
EFCore执行查询的源码
public virtual TResult Execute<TResult>(Expression query)
{
Check.NotNull(query, nameof(query));
var queryContext = _queryContextFactory.Create();
query = ExtractParameters(query, queryContext, _logger);
//获取缓存的地方
var compiledQuery
= _compiledQueryCache
//这个query就是他的key.
.GetOrAddQuery(
_compiledQueryCacheKeyGenerator.GenerateCacheKey(query, async: false),
() => CompileQueryCore<TResult>(query, _queryModelGenerator, _database, _logger, _contextType));
return compiledQuery(queryContext);
}
看一下query的结构

结论:EF的缓存机制是用生成后的表达式树做的Key哦,但是生成表达式树的那段代码的性能损耗是无法避免的了!所以!!!慎用!!!动态SQL!!!
EF性能分析(一):动态SQL性能差.从OrderBy开始分析的更多相关文章
- Oracle DB SQL 性能分析器
• 确定使用SQL 性能分析器的优点 • 描述SQL 性能分析器工作流阶段 • 使用SQL 性能分析器确定数据库更改所带来的性能改进 SQL 性能分析器:概览 • 11g 的新增功能 • 目标用户:D ...
- Oracle SQL 性能优化技巧
Select语句完整的执行顺序: SQL Select语句完整的执行顺序: 1. from子句组装来自不同数据源的数据: 2.where子句基于指定的条件对记录行进行筛选: 3.group by子句将 ...
- 动态SQL使用小结
1.什么是动态SQL? 静态 SQL:静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句必须是确定的,例如 SQL 语句中涉及的列名和表名必须是存在的.静态 SQL 语句的编 ...
- sqlt 之 分析 DB upgrade 导致SQL 性能下降 的方法 xplore
https://blog.csdn.net/lukeUnique/article/details/79331779 https://mauro-pagano.com/2014/10/27/when-t ...
- SQL性能优化案例分析
这段时间做一个SQL性能优化的案例分析, 整理了一下过往的案例,发现一个比较有意思的,拿出来给大家分享. 这个项目是我在项目开展2期的时候才加入的, 之前一期是个金融内部信息门户, 里面有个功能是收集 ...
- SQL性能分析之执行计划
一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<Inside Microsoft SQL S ...
- 使用Oracle执行计划分析SQL性能
执行计划:一条查询语句在ORACLE中的执行过程或访问路径的描述.即就是对一个查询任务,做出一份怎样去完成任务的详细方案. 如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的 ...
- Mysql高级操作学习笔记:索引结构、树的区别、索引优缺点、创建索引原则(我们对哪种数据创建索引)、索引分类、Sql性能分析、索引使用、索引失效、索引设计原则
Mysql高级操作 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 树的区别: 二叉树:可能产生不平衡,顺序数据可能会出现链表结构 ...
- 使用show profiles分析SQL性能
如何查看执行SQL的耗时 使用show profiles分析sql性能. Show profiles是5.0.37之后添加的,要想使用此功能,要确保版本在5.0.37之后. 查看数据库版本 mysql ...
随机推荐
- EAS开发
WAFII中的 数据获取与传输 首先看实例代码: DataAction:function(){ //获取选中所有列的id var selectedIds = waf("#grid" ...
- iOS开发一个制作Live Photo的工具
代码地址如下:http://www.demodashi.com/demo/13339.html 1.livePhoto简介 livePhoto是iOS 9.0 之后系统相机提供的拍摄动态照片的功能,但 ...
- php引用(&)变量引用,函数引用,对象引用和参数引用用法
php引用(&)变量引用,函数引用,对象引用和参数引用用法 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的名字访问同一个变量内容.与C语 ...
- Cocos2d-X中的ZORDER和Tag
ZORDER:是描写叙述渲染顺序的值,每一个CCNode都有ZORDER,默认是0 ZORDER越大,越后面绘制 假设ZORDER同样.那么看arrival顺序.先增加的节点先绘制 ZORDER仅仅在 ...
- C#Virtual和Override的几种组合
情况1: class A{public void Show()} class B:A{public void Show()} 编译通过,有警告让在B的方法里添加new关键字,以便将A的方法隐藏 编译时 ...
- ss - float浮动模块的高度问题 解决方案
当一个Div中的子元素都是浮动元素时,该div是没有高度的.通常会带来很多困扰,解决方案如下: 低版本统配兼容: overflow: hidden; 下面是不支持低配浏览器,而且似乎该效果对 P 标签 ...
- unity, access sprite of UGUI Image
首先需要using UnityEngine.UI; 然后调用下面语句就不报错了: Image.GetComponent<Image>().sprite 参考:http://answers. ...
- 一.软件介绍(apache lighttpd nginx)
一.软件介绍(apache lighttpd nginx) 1. lighttpd Lighttpd是一个具有非常低的内存开销,cpu占用率低,效能好,以及丰富的模块等特点.lighttpd是众多 ...
- WebView中input file的解决方法
public class MyWb extends Activity { /** Called when the activity is first created. */ WebView web; ...
- erlang supervisor simple_one_for_one实例
simple_one_for_one vs one_for_one: 相同点: 这种Restart Strategy和one_for_one基本相同(即当一个child process挂掉后,仅仅重启 ...