使用 ToList() 在实体框架中进行 SQL 查询花费太多时间

问题描述 投票:0回答:1

我正在使用 Entity Framework Core。使用此代码,获取 2000 条记录需要 1 分钟多的时间。 请帮我在几秒钟内找到数据。

var incomingEmails = acompDbContext.IncomingEmails.AsNoTracking().Where(ie => ie.ReceiverRuc == req.ReceiverRuc)
.Select(ie => new IncomingEmail
{
    // Select only necessary properties
    IncomingEmailId = ie.IncomingEmailId,
    IdStatusMail = ie.IdStatusMail,
    MessageId = ie.MessageId,
    From = ie.From,
    To = ie.To,
    Subject = ie.Subject,
    Body = ie.Body,
    AttachmentName = ie.AttachmentName,
    Attachment = ie.Attachment,
    AttachmentType = ie.AttachmentType,
    AttachmentId = ie.AttachmentId,
    EmitterRuc = ie.EmitterRuc,
    EmitterBusinessName = ie.EmitterBusinessName,
    ReceiverRuc = ie.ReceiverRuc,
    Date = ie.Date,
    Valid = ie.Valid
}).ToListAsync();

我尝试减少数据,但我需要全部 2000 条记录。

sql-server performance entity-framework-core
1个回答
0
投票

我想到三件事。首先检查此 ReceiverRuc 列是否已在数据库中建立索引。针对非索引列查询数据会更慢,尤其是对于包含大量数据的表。

其次,这个查询似乎确实提取了更多它可能应该提取的信息。我看到的警告标志是电子邮件正文和附件。当拉动数千行进行迭代时,请考虑省略那些不是“立即”必要的重量级字段。如果您确实希望最终迭代所有 2000 个结果,您可以通过 ID 获取这些繁重的字段,甚至可以将它们批量化,并在处理电子邮件记录时一次获取 10 或 100 个较小的组。 第三是附件本身,这是电子邮件表中的一列还是单独附件表中的一行?如果是后者,您将希望将其投影到简化的附件对象,同样只包含您需要的列:

.Select(ie => new IncomingEmail { // Select only necessary properties // ... Attachment = new Attachment { ... } // ... }).ToListAsync();

如果您使用 ToListAsync(),查询本身需要 
await

为了了解正在发生的情况,您可以做的下一件事是针对数据库运行探查器以捕获正在运行的 SQL 语句。需要注意的罪魁祸首是诸如延迟加载调用之类的事情。例如,如果您启动此方法并捕获一条似乎从电子邮件加载数据的 SQL 行,但随后看到 2000 条左右的附加 SQL 语句提取与附件周围某个表相关的数据(假设附件是另一个表中的一行) )那么您可能会遇到延迟加载引用所包含的附件实体的问题。这个问题本身可以通过将附件投影到新容器中来解决。 (上面的第三点)不过,在读取数据时,分析器可以帮助识别与延迟加载相关的性能问题。您还可以检查实际运行的 SQL 语句以获得执行计划,该计划可以提供性能提示。

© www.soinside.com 2019 - 2024. All rights reserved.