简体   繁体   English

EF Core 查询非常慢,表之间有很多关系

[英]EF Core query is extremely slow with many relations between tables

I have an EF Core query like this:我有一个这样的 EF Core 查询:

var existingViolations = await _context.Parent
       .Where(p => p.ProjectId == projectId)
          .Include(p => p.Relation1)
          .Include(p => p.Relation2)
               .ThenInclude(r => r.Relation21)
          .Include(p => p.Relation3)
        .AsSplitQuery()
        .ToListAsync();

This query usually takes between 55-65 seconds which can sometimes cause database timeouts.此查询通常需要 55-65 秒,这有时会导致数据库超时。 All the tables included in the query, including the parent table, contain anywhere from 30k-60k rows and 3-6 columns each.查询中包含的所有表(包括父表)都包含 30k-60k 行和 3-6 列。 I have tried splitting it up into smaller queries using LoadAsync() like this:我尝试使用LoadAsync()将其拆分为较小的查询,如下所示:

_context.ChangeTracker.LazyLoadingEnabled = false;
_context.ChangeTracker.AutoDetectChangesEnabled = false;

await _context.Relation1.Where(r1 => r1.Parent.ProjectId == projectId).LoadAsync();

await _context.Relation2.Where(r2 => r2.Parent.ProjectId == projectId).Include(r2 => r2.Relation21).LoadAsync();

await _context.Relation3.Where(r3 => r3.Parent.ProjectId == projectId).LoadAsync();

var result = await _context.Parent.Where(p => p.ProjectId == projectId).ToListAsync();

That shaves about 5 seconds off the query time, so nothing to brag about.这将查询时间缩短了大约 5 秒,所以没什么可吹嘘的。 I've done some timings, and it's the last line ( var result = await _context.Parent.Where(p => p.ProjectId == projectId).ToListAsync(); ) that takes by far the longest to complete, about 90% of the spent time.我已经做了一些计时,这是迄今为止完成时间最长的最后一行( var result = await _context.Parent.Where(p => p.ProjectId == projectId).ToListAsync(); ),大约 90花费时间的百分比。

How can I optimize this further?我该如何进一步优化呢?

Without seeing the real entities and how they might be configured, it's anyone's guess.在没有看到真实实体以及它们如何配置的情况下,这是任何人的猜测。

Generally speaking when looking at performance issues like this, the first thing I would look to tackle is "what is this data being loaded for?"一般来说,在查看此类性能问题时,我首先要解决的是“加载这些数据的目的是什么?” Typically when I see queries using a lot of Include s, this is something like a read operation to be loaded for a view or computation based on that selected data.通常,当我看到使用大量Include的查询时,这类似于基于所选数据为视图或计算加载的读取操作。 Projection down to a simpler model can help significantly here if you really only need a few columns from each table to satisfy your needs.如果您真的只需要每个表中的几列来满足您的需求,那么投影到更简单的 model 在这里会大有帮助。 The benefit of projection using a Select across the related data to fill either a DTO/ViewModel class for a view or an an anonymous type for a computation is that Include will want to pass all columns for all eager loaded tables in the one go, where projection will only pass back the columns referenced.在相关数据中使用Select进行投影以填充 DTO/ViewModel class 用于视图或匿名类型用于计算的好处是, Include将希望传递一个 Z34D1F91 中所有急切加载表的所有列,其中 FB12E514B98576A,投影只会传回引用的列。 This can be critically important where tables can contain things like large text/binary columns that you don't need at all or right away.当表可以包含您根本不需要或立即不需要的大型文本/二进制列之类的内容时,这可能非常重要。 This is also very important in cases where the database server might be some distance from the consuming client or web server.这在数据库服务器可能与消费客户端或 web 服务器有一定距离的情况下也非常重要。 Less data over the wire = faster performance, though the issue right now sounds like the DB query itself.网络上的数据越少 = 性能越快,尽管现在的问题听起来像是数据库查询本身。

The next thing to check would be the relationships between all of the tables and any relevant configuration in EF vs. the table design.接下来要检查的是所有表和 EF 中的任何相关配置与表设计之间的关系。 Waiting a minute to pull a few records from 30-60k rows is ridiculously long and I would be highly suspect of some flawed relationship mapping that isn't using FKs/indexes.等待一分钟从 30-60k 行中提取几条记录的时间太长了,我高度怀疑某些不使用 FK/索引的有缺陷的关系映射。 Another place to look would be to run a profiler against the database to capture the exact SQL statement(s) being run, then execute those manually to investigate their execution plan which might reveal schema problems or some weirdness with the entity relationship mapping producing very inefficient queries.另一个值得关注的地方是对数据库运行分析器以捕获正在运行的确切 SQL 语句,然后手动执行这些语句以调查其执行计划,这可能会揭示架构问题或实体关系映射产生的一些怪异导致效率非常低查询。

The next thing to check would be to use a process of elimination to see if there is a bad relationship.接下来要检查的是使用消除过程来查看是否存在不良关系。 Eliminate each of the eager load Include statements one by one and see how long each the query scenario takes.一个一个地消除每个急切的加载Include语句,看看每个查询场景需要多长时间。 If there is a particular Include that is responsible for a drastic slow-down, drill down into that relationship to see why that might be.如果有一个特定的Include导致急剧减速,请深入研究该关系以了解原因。

That should give you a couple avenues to check.这应该给你几个途径来检查。 Consider revising your question with the actual entities and any further troubleshooting results.考虑使用实际实体和任何进一步的故障排除结果修改您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM