实体框架核心第一个查询与后续查询性能

如何解决实体框架核心第一个查询与后续查询性能

最近我一直在想,实体框架中的第一个查询和随后的相同查询性能之间出现巨大差异的原因是什么?是因为Entity Framework具有某种内部缓存来缓存查询结果,并且随后对同一查询的所有调用均使用该缓存结果?

要正确理解问题,以下是我到目前为止进行的一些测试

for (var i = 0; i < 20; i++)
{
    var sw = Stopwatch.StartNew();

    var departments = _sampleContext.Departments.AsNoTracking().ToList();

    sw.Stop();

    Console.WriteLine($"Run {i+1} took {sw.ElapsedMilliseconds} ms");
}

输出:

Run 1 took 2708 ms
Run 2 took 350 ms
Run 3 took 421 ms
Run 4 took 300 ms
Run 5 took 329 ms
Run 6 took 319 ms
Run 7 took 301 ms
Run 8 took 303 ms
Run 9 took 310 ms
Run 10 took 342 ms
Run 11 took 284 ms
Run 12 took 322 ms
Run 13 took 359 ms
Run 14 took 297 ms
Run 15 took 291 ms
Run 16 took 288 ms
Run 17 took 268 ms
Run 18 took 309 ms
Run 19 took 299 ms
Run 20 took 298 ms

在这里您可以看到第一轮和第二轮之间有很大的差异。

这可能是什么原因?

除此之外,我还尝试了不使用如下所示的Entity Framework来复制相同的场景

var sqlConnection = new SqlConnection(_configuration.GetSection("ConnectionStrings:DefaultConnection").Value);

sqlConnection.Open();

for (var i = 0; i < 20; i++)
{
    var sw = Stopwatch.StartNew();

    var sqlCommand = new SqlCommand("select * from Departments",sqlConnection);

    using var sqlDataReader = sqlCommand.ExecuteReader();

    if (sqlDataReader.HasRows)
    {
        while (sqlDataReader.Read())
        {
            var id = sqlDataReader.GetInt32(0);
            var name = sqlDataReader.GetString(1);
        }
    }

    sw.Stop();

    Console.WriteLine($"Run {i + 1} took {sw.ElapsedMilliseconds} ms");
}

输出:

Run 1 took 499 ms
Run 2 took 300 ms
Run 3 took 276 ms
Run 4 took 275 ms
Run 5 took 273 ms
Run 6 took 256 ms
Run 7 took 288 ms
Run 8 took 309 ms
Run 9 took 285 ms
Run 10 took 280 ms
Run 11 took 292 ms
Run 12 took 308 ms
Run 13 took 283 ms
Run 14 took 267 ms
Run 15 took 290 ms
Run 16 took 276 ms
Run 17 took 277 ms
Run 18 took 286 ms
Run 19 took 283 ms
Run 20 took 273 ms

在第一次和第二次运行之间也有区别,但是没有实体框架那么大。

我正在使用EF Core 3.1

根据@Larnu的评论,可能是由于SQL Server的查询计划缓存,所以我试图在每次迭代中运行稍微不同的查询,如下所示

ADO.NET版本

var sqlCommand = new SqlCommand($"select * from Departments where ID > {i}",sqlConnection);

输出:

Run 1 took 494 ms
Run 2 took 274 ms
Run 3 took 304 ms
Run 4 took 276 ms
Run 5 took 731 ms
Run 6 took 475 ms
Run 7 took 576 ms
Run 8 took 276 ms
Run 9 took 275 ms
Run 10 took 291 ms
Run 11 took 271 ms
Run 12 took 253 ms
Run 13 took 269 ms
Run 14 took 262 ms
Run 15 took 270 ms
Run 16 took 303 ms
Run 17 took 261 ms
Run 18 took 296 ms
Run 19 took 275 ms
Run 20 took 661 ms

实体框架版本:

var departments = _sampleContext.Departments.Where(x=>x.ID > i).AsNoTracking().ToList();

输出:

Run 1 took 2377 ms
Run 2 took 274 ms
Run 3 took 272 ms
Run 4 took 260 ms
Run 5 took 276 ms
Run 6 took 281 ms
Run 7 took 319 ms
Run 8 took 506 ms
Run 9 took 318 ms
Run 10 took 265 ms
Run 11 took 269 ms
Run 12 took 276 ms
Run 13 took 283 ms
Run 14 took 256 ms
Run 15 took 253 ms
Run 16 took 258 ms
Run 17 took 277 ms
Run 18 took 298 ms

我想第一次查询和第二次查询之间的区别还是很大的,那是因为SQL Server的查询计划缓存还是其他原因?

解决方法

我认为这将回答您的问题:https://github.com/dotnet/efcore/issues/9347

长话短说,在第一次运行时为上下文建立模型需要时间。模型越大,花费的时间越多。

您可以发现以下发现:

首次查询的总毫秒数126078

第二个查询的总毫秒数17

首次保存的总毫秒数121

每秒保存的总毫秒数10

团队知道,第一个查询中的模型构建需要时间,他们已经减轻了一点时间,但是正如评论所提到的那样:

我们已经稍微改善了模型构建的性能,但是您最好的选择是等待编译模型#1906

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-