GraphQL 一对多性能问题和限制

Posted

技术标签:

【中文标题】GraphQL 一对多性能问题和限制【英文标题】:GraphQL one to many performance issue and limitation 【发布时间】:2021-04-02 04:16:33 【问题描述】:

我有一个带有 2 个表的数据库 => 玩家(10k 条目)和目标(100k 条目)。我在他们之间有一对多的关系(玩家有很多目标)

@Entity()
@ObjectType()
class Player 
  @Field(() => ID)
  @PrimaryGeneratedColumn("uuid")
  id: string;

  @Field(() => [Goal])
  @OneToMany(
    () => Goal,
    goal => goal.player
  )
  goals: Goal[];
  ...


@Entity()
@ObjectType()
class Goal 
  @Field(() => ID)
  @PrimaryGeneratedColumn("uuid")
  id: string;

  @ManyToOne(
    () => Player,
    player => player.id
  )
  player: Player;
  ...

我想查询玩家及其目标,以便在我的客户端应用中显示玩家排名

query scorers
  players
    id
    totalGoals
  

播放器解析器如下所示

@Resolver(Player)
class PlayerResolver 
  @Query(() => [Player])
  async players() 
    return this.playerRepository.createQueryBuilder("player").getMany();
  
  @FieldResolver()
  async totalGoals(@Root() player: Player) 
    return this.goalRepository.count( player );
  

这并不高效,因为它在后台创建了一个 SQL 查询来请求每个玩家的目标。所以它可能是 10k 查询。这是最好的策略吗?另外我想知道我怎么可能按进球数来排序球员。 我正在使用type-graphqltypeorm

【问题讨论】:

将 totalGoals 缓存为播放器中的字段/道具,不应依赖 [reading] 解析器...更新目标 instert 看到这个***.com/questions/63663128/… 一次查询 10k 玩家似乎是 imo 的实际问题。 @xadm 在 SQL 数据库中创建缓存字段/prop 是否常见?你对此有参考吗? 它经常使用且成本高昂...您如何按总进球数对球员进行排序...在一个赛季中?复杂性呈指数级增长 【参考方案1】:

您可以尝试提前使用连接构建查询(在查询解析器级别,使用 @Info 读取请求的字段)或使用 DataLoader 库来批处理查询并解决 N + 1 问题。

【讨论】:

以上是关于GraphQL 一对多性能问题和限制的主要内容,如果未能解决你的问题,请参考以下文章

大规模的一对多性能

一对多关系中的 PHP 和 API 调用性能和最佳实践

通过大量一对多映射提高查询性能

graphql/graphcool:如何编写一个连接一对一和一对多关系的突变

CoreData 性能:基于多对多关系

如何过滤graphQL一对多关系中的查询?