MichalLytek / typegraphql-prisma

Prisma generator to emit TypeGraphQL types and CRUD resolvers from your Prisma schema

Home Page:https://prisma.typegraphql.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

N+1 select issue due to use of findUniqueOrThrow in relation resolvers

sam-lewis opened this issue · comments

Describe the Bug
It appears that the switch to findUniqueOrThrow() in 3ea20f6 has introduced an N+1 select issue.

I have observed that Prisma's built-in dataloader batches findUnique() queries but not findUniqueOrThrow()queries resulting in N+1 selects in recent versions of typegraphql-prisma.

To Reproduce

  • Clone the typegraphql-prisma repo
  • Open examples/2-basic
  • Update the dependencies:
"@prisma/client": "~4.13.0"
"prisma": "~4.13.0"
"typegraphql-prisma": "0.25.0"
  • Enable Prisma Query logging in index.ts:
  const prisma = new PrismaClient({
    log: ['query']
  })
  • Run npm install
  • Run npm run generate
  • Run npm start
  • Execute GraphQL Query:
query ExampleQuery {
  users {
    id
    posts {
      id
    }
  }
}
  • Observe N+1 select statements (see logs below)

Expected Behavior
Fewer select statements against the database as seen with previous versions (see logs below)

Logs
With typegraphql-prisma 0.25.0:

prisma:query SELECT `main`.`User`.`id`, `main`.`User`.`email`, `main`.`User`.`name` FROM `main`.`User` WHERE 1=1 LIMIT ? OFFSET ?
prisma:query SELECT `main`.`User`.`id` FROM `main`.`User` WHERE (`main`.`User`.`id` = ? AND 1=1) LIMIT ? OFFSET ?
prisma:query SELECT `main`.`Post`.`id`, `main`.`Post`.`createdAt`, `main`.`Post`.`updatedAt`, `main`.`Post`.`published`, `main`.`Post`.`title`, `main`.`Post`.`content`, `main`.`Post`.`authorId` FROM `main`.`Post` WHERE `main`.`Post`.`authorId` IN (?) LIMIT ? OFFSET ?
prisma:query SELECT `main`.`User`.`id` FROM `main`.`User` WHERE (`main`.`User`.`id` = ? AND 1=1) LIMIT ? OFFSET ?
prisma:query SELECT `main`.`Post`.`id`, `main`.`Post`.`createdAt`, `main`.`Post`.`updatedAt`, `main`.`Post`.`published`, `main`.`Post`.`title`, `main`.`Post`.`content`, `main`.`Post`.`authorId` FROM `main`.`Post` WHERE `main`.`Post`.`authorId` IN (?) LIMIT ? OFFSET ?

With typegraphql-prisma 0.23.2:

prisma:query SELECT `main`.`User`.`id`, `main`.`User`.`email`, `main`.`User`.`name` FROM `main`.`User` WHERE 1=1 LIMIT ? OFFSET ?
prisma:query SELECT `main`.`User`.`id` FROM `main`.`User` WHERE `main`.`User`.`id` IN (?,?) LIMIT ? OFFSET ?
prisma:query SELECT `main`.`Post`.`id`, `main`.`Post`.`createdAt`, `main`.`Post`.`updatedAt`, `main`.`Post`.`published`, `main`.`Post`.`title`, `main`.`Post`.`content`, `main`.`Post`.`authorId` FROM `main`.`Post` WHERE `main`.`Post`.`authorId` IN (?,?) LIMIT ? OFFSET ?

Environment:

  • OS: macOS
  • Node v18.16.0
  • typegraphql-prisma version 0.25.0
  • Prisma version 4.13.0
  • TypeScript version 4.9.4

Additional Context
Nice work on the project, its awesome :-)

I believe we're seeing this issue as well.

Could the Prisma team add findUniqueOrThrow to their list of "dataloader approved" funcs to resolve this? Or would typegraphql-prisma need to generate slightly different models? I've been reading through the fluent API, could that be used here?

I was able to get around this in my specific implementation, and by using Prisma's Fluent API I got a 97% perf boost (!!!).

IDK how hard it would be to get the generated code to make use of the Fluent API, but if you see an easy way that might help this category of issue.

https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#fluent-api

I was able to get around this in my specific implementation, and by using Prisma's Fluent API I got a 97% perf boost (!!!).

How does that compare to manually editing the generated relation resolver code to use findUnique()?

How does that compare to manually editing the generated relation resolver code to use findUnique()?

Oh yeah actually really good as well, probably here the only value of the Fluent API was to get the dataloader to pay attention, then.

For reference, I am managed to handle it forcibly with middleware, as shown in the following link. 😒
prisma/prisma#18838 (comment)

Closing as looks like it's fixed by prisma/prisma#16625 🔒

@sam-lewis If the issue still occurs, please let me know 😉