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 ...
随机推荐
- python中好用的pip
1.windows/linux 下安装pip见上篇博客 http://www.cnblogs.com/Edwardzhao/p/5856924.html 2.好用的方法 pip install xxx ...
- Python多线程问题的资料查找与汇总
Python多线程问题的资料查找与汇总 声明: 1)本报告由博客园bitpeach撰写,版权所有,免费转载,请注明出处,并请勿作商业用途. 2)若本文档内有侵权文字或图片等内容,请联系作者bitpea ...
- static、final修饰符、内部类
static修饰符: static修饰符能够与属性.方法和内部类一起使用,表示静态的.类中的静态变量和静态方法能够与类名一起使用.不须要创建一个类的对象来訪问该类的静态成员. class Static ...
- 10-hibernate单表操作-组件属性
组件属性: 实体类中某个属性属于用户自定义的类的对象,比如在实体类中某个属性是自定义类的对象: 这个Address是一个用户自定义类. 该自定义类Address定义如下: //地址类 public c ...
- Grunt快速使用笔记
本篇文章由:http://xinpure.com/grunt-quick-note/ http://www.gruntjs.net/getting-started Grunt中文网 安装 Grunt ...
- C# -- 使用递归列出文件夹目录及目录下的文件 神技do{}while(false)
C# -- 使用递归列出文件夹目录及目录下的文件 使用递归列出文件夹目录及目录的下文件 1.使用递归列出文件夹目录及目录下文件,并将文件目录结构在TreeView控件中显示出来. 新建一个WinFor ...
- sql getdate()生成单据号
select replace( replace( replace( replace(convert(varchar(23),getdate(),121),'-',''),':',''),' ','') ...
- tcp_recvmsg 函数具体解释
看了非常多网上关于tcp_recvmsg的文章,感觉解释的不太到位,或者非常多都是空口说白话,昨天分析了一下午tcp_recvmsg.感觉了解了十之八九,如今贴出来和大家分享一下. 须要背景:了解tc ...
- 4~20mA模拟输出(电流环)应用笔记(转)
https://zm12.sm-tc.cn/?src=http%3A%2F%2Fwww.aichengxu.com%2Fview%2F5397788&uid=d2f68cd7fd230c162 ...
- javascript和html中unicode编码和字符转义的详解
1.html中的转义:在html中如果遇到转义字符(如“ ”),不管你的页面字符编码是utf-8亦或者是GB2312,都会直接打印成相应的字符:而当遇到(如:“\u8981”[此处的8981是16进制 ...