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开始分析的更多相关文章

  1. Oracle DB SQL 性能分析器

    • 确定使用SQL 性能分析器的优点 • 描述SQL 性能分析器工作流阶段 • 使用SQL 性能分析器确定数据库更改所带来的性能改进 SQL 性能分析器:概览 • 11g 的新增功能 • 目标用户:D ...

  2. Oracle SQL 性能优化技巧

    Select语句完整的执行顺序: SQL Select语句完整的执行顺序: 1. from子句组装来自不同数据源的数据: 2.where子句基于指定的条件对记录行进行筛选: 3.group by子句将 ...

  3. 动态SQL使用小结

    1.什么是动态SQL? 静态 SQL:静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句必须是确定的,例如 SQL 语句中涉及的列名和表名必须是存在的.静态 SQL 语句的编 ...

  4. sqlt 之 分析 DB upgrade 导致SQL 性能下降 的方法 xplore

    https://blog.csdn.net/lukeUnique/article/details/79331779 https://mauro-pagano.com/2014/10/27/when-t ...

  5. SQL性能优化案例分析

    这段时间做一个SQL性能优化的案例分析, 整理了一下过往的案例,发现一个比较有意思的,拿出来给大家分享. 这个项目是我在项目开展2期的时候才加入的, 之前一期是个金融内部信息门户, 里面有个功能是收集 ...

  6. SQL性能分析之执行计划

    一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<Inside Microsoft SQL S ...

  7. 使用Oracle执行计划分析SQL性能

    执行计划:一条查询语句在ORACLE中的执行过程或访问路径的描述.即就是对一个查询任务,做出一份怎样去完成任务的详细方案. 如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的 ...

  8. Mysql高级操作学习笔记:索引结构、树的区别、索引优缺点、创建索引原则(我们对哪种数据创建索引)、索引分类、Sql性能分析、索引使用、索引失效、索引设计原则

    Mysql高级操作 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 树的区别: 二叉树:可能产生不平衡,顺序数据可能会出现链表结构 ...

  9. 使用show profiles分析SQL性能

    如何查看执行SQL的耗时 使用show profiles分析sql性能. Show profiles是5.0.37之后添加的,要想使用此功能,要确保版本在5.0.37之后. 查看数据库版本 mysql ...

随机推荐

  1. Wpf修改控制的大小

    Wpf修改控制的大小 随窗体的改变而改变 在WINFORM中设置控件的Anchor属性就行了 在WPF中没有Anchor属性 但可以在布局中设置 相关属性实现同样的效果 相关属性 Horizontal ...

  2. Fedora 28 设置yum代理

    编辑  vi /etc/dnf/dnf.conf 文件 添加一行代理设置:proxy=http://****:****

  3. JMeter 十三:生成 report dashboard

    参考:http://jmeter.apache.org/usermanual/generating-dashboard.html JMeter 3.x开始,可以生成HTML格式的report . 注意 ...

  4. 演示程序之打游戏 -- 慕司板IAP15

    上位机和协议制定我的大学舍友(他的微博:http://weibo.com/lesshst? topnav=1&wvr=5&topsug=1)毕业前百忙之中使用Python花了一个下午完 ...

  5. CosmosEngine - Unity3D /2D 轻量级游戏开发框架

    CosmosEngine https://github.com/mr-kelly/CosmosEngine 快速入门 简介 特性 约定 整体架构图 使用经验 工作流 未来功能 快速入门 1.将NGUI ...

  6. EAS开发

    WAFII中的 数据获取与传输 首先看实例代码: DataAction:function(){ //获取选中所有列的id var selectedIds = waf("#grid" ...

  7. Android版俄罗斯方块的实现

    学习Android的基本开发也有一段时间了,可是由于没有常常使用Android渐渐的也就忘记了. Android编程学的不深,不过为了对付逆向,可是有时还是会感到力不从心的.毕竟不是一个计算机专业毕业 ...

  8. IBATIS + ORACLE(二)

      迁移时间:2017年6月1日16:09:02 Author:Marydon (四)IBATIS + ORACLE UpdateTime--2017年5月31日10:49:34 第二部分:提升篇 1 ...

  9. maven编译war包,pom中必须有的几个dependency

    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> ...

  10. centos 7 生成文件名乱码的问题如何解决?

    在应用脚本生成文件时,发现生成的文件名称出现乱码(似麻将一样).刚开始找来找去,以为是复制粘贴的原因,复制时复制了特殊字符导致的,结果修改源文件后发现生成的文件名还是乱码.后来在执行脚本时,提示&qu ...