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. ASUS主板ALC887声卡,RTL81XX网卡,黑苹果驱动安装

    折腾了一下午终于在黑苹果上成功的安装了网卡,声卡驱动: 我的配置: 主板 ASUS b75m-a 声卡 ALC887 网卡 RTL8168F 安装所需工具: MutiBest 下载OS对应的版本即可  ...

  2. 服务器提交了协议冲突. Section=ResponseHeader Detail=CR...的解决方案总结

    今天在HttpWebRequest发送一个网页请求的时候,HttpWebResponse返回了一个奇怪的错误信息: 这个Http协议请求类可是微软封装的,我使用的流程可是中规中矩,不可能是我写错代码, ...

  3. Cannot make a static reference to the non-static method的解决方法

    报错原因:在一个类中写了一个public String getContent()方法和一个main()方法,getContent()方法中包含了getClass()方法,在main()方法中直接调用了 ...

  4. sqlite 小刀 初试

    SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是嵌入式的,而且目前已经在很多嵌入式产 ...

  5. pandas知识点汇总

    ## pandas基础知识汇总 1.时间序列 import pandas as pd import numpy as np import matplotlib.pyplot as plt from d ...

  6. jmeter ---测试TCP服务器/模拟发送TCP请求

    jmeter测试TCP服务器/模拟发送TCP请求 jmeter测试TCP服务器,使用TCP采样器模拟发送TCP请求. TCP采样器:打开一个到指定服务器的TCP / IP连接,然后发送指定文本并等待响 ...

  7. 使用结构(C# 编程指南)

    struct 类型适于表示 Point.Rectangle 和 Color 等轻量对象. 尽管使用自动实现的属性将一个点表示为类同样方便,但在某些情况下使用结构更加有效. 例如,如果声明一个 1000 ...

  8. AHM ---301重定向

    使用amh.conf 或重新创建一个test.conf配置文件 .保存目录 /usr/local/nginx/conf/rewrite 例如跳到 www.shuaixingkeji.com if ($ ...

  9. 通过Socket连接一次传输多个文件

    近期在做一个通过WIFI在手机之间传输文件的功能.须要在手机之间建立一个持久的Socket 连接并利用该连接数据传输.能够一次传输一个或多个文件. 在一次传输多个文件时,遇到了一个困难:怎样在接收文件 ...

  10. PHP 抽象类的使用

    //抽象类就是一个模版 abstract class db{ /* 参数:sql语句 返回值:索引的数组 */ abstract public function test($str); //没有方法体 ...