gpt4 book ai didi

performance - 如何提高使用多个 Include 的 EF Core 查询的性能

转载 作者:行者123 更新时间:2023-12-03 00:30:18 26 4
gpt4 key购买 nike

我有这个查询,为了简洁起见,我将简化它:

public IQueryable<User> GetByIdAsync(Guid userId)
{
return MyContext
.Users
//Bunch of Includes
//Most of which have a ThenInclude
//Followed by another ThenInclude
.FirstOrDefaultAsync(u => u.Id == userId)
}

当为大约 100 个用户运行时,需要超过 15 秒(在我的计算机上本地运行)。不太好。

我尝试使用 AsNoTracking(),并将其更改为使用已编译的查询,如下所示:

private static Func<MyContext, Guid, Task<User>> _getByIdAsync =
EF.CompileAsyncQuery((MyContext context, Guid userId) =>
context
.Users
//Same Includes as above
.Where(u => u.Id == userId)
.FirstOrDefault());

public IQueryable<User> GetByIdAsync(Guid userId)
{
return await _getByIdAsync(userId);
}

仍然没有区别。

我已经查看了相关线程的答案,它建议使用普通的旧 SQL:

https://stackoverflow.com/a/16977218/9778248

我已经看过这个答案,其中提到了聚集索引:

https://stackoverflow.com/a/55557237/9778248

我当然不能排除任何包含,因为客户端依赖于所有这些信息。现阶段也不能选择重新设计。

问题

  1. 还有其他可以提高性能的选项吗?
  2. 我在任何子表索引中都看不到任何 CLUSTEREDNONCLUSTERED 标记。这是否值得研究?如果值得研究,是否可以向我指出任何文档来解释如何使用 EF(或不使用 EF)进行更新?

最佳答案

你有很多方法,但这取决于情况。

  1. 您有 .FirstOrDefaultAsync(u => u.Id == userId) 这意味着对于 100 个用户,您将访问数据库 100 次,因此总计 15 000/100 == 等于 150 毫秒根据要求。为了改进它,尝试使用 in 子句一次获取所有 100 个用户,例如 .Where(u=> userIds.contains(u.Id))

示例。

private static Func<MyContext, Guid, Task<List<User>>> _getByIdAsync =
EF.CompileAsyncQuery((MyContext context, List<Guid> userIds) =>
context
.Users
//Same Includes as above
.Where(u => userIds.Contains(u.Id))).ToListAsync();
  1. 我对您的数据结构一无所知,但如果您可以使用联接编写 linq,它可能会更快,因为对于一个请求中的多对多,EF 可以每次依赖项都访问数据库。

如何使用联接进行查询的示例

var query = (from users in context.Users
join otherTable in context.OtherTable on users.Id equals otherTable.UserId).ToList();
  • Ef尝试适应通用目的,但有时当你知道你的数据时,只有你才能做得更好,当我有存储库方法来一一获取数据时,我曾经遇到过与你类似的问题,但后来我编写了新方法使用数组获取数据,该方法负责连接数据,通过 EF 基本上不可能快速完成。 所以我所说的在一个请求中加载所有一对一,然后从数据库读取并使用另一个查询去获取您需要的多对多。
  • 还可以获取sql查询
  • 您可以使用此示例获取sql

    public IQueryable<User> GetByIdAsync(Guid userId)
    {
    var = query = MyContext
    .Users
    //Bunch of Includes
    //Most of which have a ThenInclude
    //Followed by another ThenInclude
    var sql = query.ToSql(); // <--------------------------- sql query
    return query.FirstOrDefaultAsync(u => u.Id == userId)
    }

    并使用sql查询来分析并查看其是否使用索引。

    最后,我真的很讨厌这样的方法 public IQueryable GetByIdAsync(Guid userId) 问题是大多数时候你不需要所有包含的内容,但你开始越来越多地使用它们并变得依赖这就是为什么我建议使用没有存储库模式的 EF,EF 本身是存储库,仅从数据库获取您需要的数据。

    关于performance - 如何提高使用多个 Include 的 EF Core 查询的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57643491/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com