c# - ASP.NET Core 3.1 实体框架存在查询持续时间
问题描述
我正在尝试在 ASP.NET Core 3.1 MVC 应用程序中分析数据库优先的 EF SQL 查询,这似乎有点浪费时间。
在使用秒表并努力获得我想要的粒度之后,我安装了 MiniProfiler(如果你没有它,那就太棒了,得到它)。
简而言之,该函数将接收一个以逗号分隔的零件 ID 字符串,并返回一个工单基本 ID 的字符串 [];
string[] part_array = part.Split(',');
string[] base_id_array = { };
using (MiniProfiler.Current.Step("TestDB"))
{
using (DB_Access.AccessContext db_context = new DB_Access.AccessContext())
{
var query = from a in db_context.WorkOrder.AsNoTracking()
where part_array.Contains(a.User2)
select new
{
a.BaseId
};
if (query != null)
{
if (query.Any())
{
foreach (var item in query)
{
Array.Resize(ref base_id_array, base_id_array.Length + 1);
base_id_array[base_id_array.GetUpperBound(0)] = item.BaseId;
}
}
}
}
}
MiniProfiler 显示以下内容;
所以首先 EF 执行一个 EXIST 查询,耗时 147.7ms
然后 EF 关闭连接,重新打开,执行实际的 SELECT 查询,只需要 40.4ms
我想问题是三方面的;
- 为什么 EF 执行 EXIST 查询?
- 为什么查询要花这么长时间?
- 为什么连接在同一个 using 语句中被关闭和重新打开?
解决方案
为什么 EF 执行 EXIST 查询?
因为您在代码中有下一行:
if (query.Any())
这将导致您的第一个查询。首先实现查询并使用结果:
var queryResults = (from a in db_context.WorkOrder.AsNoTracking()
where part_array.Contains(a.User2)
select new
{
a.BaseId
})
.ToList();
foreach (var item in queryResults)
{
Array.Resize(ref base_id_array, base_id_array.Length + 1);
base_id_array[base_id_array.GetUpperBound(0)] = item.BaseId;
}
您不需要null
检查(因为您将本地分配给一个变量,ToList
如果在数据库中没有找到结果,则返回空变量)并且Any
(foreach
将为您处理)。
为什么查询要花这么长时间?
似乎 MiniProfiler 没有说查询在数据库端需要多长时间,它说需要多长时间ExecuteReader
。我将假设这是一些运行一次的测试代码,因此由于 JIT 编译,它可能需要很长时间(比选择时间更长),并且后续调用需要更少的时间,因为 JIT 编译已经为它执行了。但我建议使用数据库探查器检查查询。
推荐阅读
- reactjs - 为什么要在 ReactJS 教程的 Time Travel 部分删除构造函数
- java - 如何将用户名传递到 Spring Boot 安全性的 application.properties 的登录 SQL 代码中?
- php - Laravel 雄辩的条件关系
- javascript - 在 vue.js 中使用带有渲染函数的导入 sass 文件
- awk - 如果其中一列有字母,则跳过该行的操作 - bash
- oracle - CI 连接到 oracle 11g
- python - PyAudio 无法安装
- python - 在 Z3 中使用固定字符定义位向量
- android - 移动应用的 Google OAuth 同意屏幕的值
- javascript - 将 VNode 渲染为 html 字符串