From 2333c200025f3b697c1a3fb9354cd6fdda52bfae Mon Sep 17 00:00:00 2001 From: Jan Piotrowski Date: Thu, 4 Apr 2024 16:10:55 +0200 Subject: [PATCH] chore(query-optimization-performance): Add `()` to queries (#5806) --- .../100-query-optimization-performance.mdx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx b/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx index 90d8835feb..239413acad 100644 --- a/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx +++ b/content/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx @@ -21,7 +21,7 @@ Alternatively, if you are only interested in the time taken to run a query, you The n+1 problem occurs when you loop through the results of a query and perform one additional query **per result**, resulting in `n` number of queries plus the original (n+1). This is a common problem with ORMs, particularly in combination with GraphQL, because it is not always immediately obvious that your code is generating inefficient queries. -### Solving n+1 in GraphQL with findUnique and Prisma Client's dataloader +### Solving n+1 in GraphQL with findUnique() and Prisma Client's dataloader
@@ -36,9 +36,9 @@ The n+1 problem occurs when you loop through the results of a query and perform
-The Prisma Client dataloader automatically **batches** `findUnique` queries that ✔ occur in the same tick and ✔ have the same `where` and `include` parameters. +The Prisma Client dataloader automatically **batches** `findUnique()` queries that ✔ occur in the same tick and ✔ have the same `where` and `include` parameters. -Automatic batching of `findUnique` is particularly useful in a **GraphQL context**. GraphQL runs a separate resolver function for every field, which can make it difficult to optimize a nested query. +Automatic batching of `findUnique()` is particularly useful in a **GraphQL context**. GraphQL runs a separate resolver function for every field, which can make it difficult to optimize a nested query. For example - the following GraphQL runs the `allUsers` resolver to get all users, and the `posts` resolver **once per user** to get each user's posts (n+1): @@ -81,7 +81,7 @@ This results in a single SQL query: } ``` -However, the resolver function for `posts` is then invoked **once per user**. This results in a `findMany` query **✘ per user** rather than a single `findMany` to return all posts by all users (expand CLI output to see queries). +However, the resolver function for `posts` is then invoked **once per user**. This results in a `findMany()` query **✘ per user** rather than a single `findMany()` to return all posts by all users (expand CLI output to see queries). @@ -150,7 +150,7 @@ const User = objectType({ -Instead, use `findUnique` in combination with [the fluent API](/orm/prisma-client/queries/relation-queries#fluent-api) (`.posts()`) as shown to return a user's posts. Even though the resolver is called once per user, the Prisma dataloader in Prisma Client **✔ batches the `findUnique` queries**. +Instead, use `findUnique()` in combination with [the fluent API](/orm/prisma-client/queries/relation-queries#fluent-api) (`.posts()`) as shown to return a user's posts. Even though the resolver is called once per user, the Prisma dataloader in Prisma Client **✔ batches the `findUnique()` queries**. @@ -209,21 +209,21 @@ const User = objectType({ -If the `posts` resolver is invoked once per user, the dataloader in Prisma Client groups `findUnique` queries with the same parameters and selection set. Each group is optimized into a single `findMany`. +If the `posts` resolver is invoked once per user, the dataloader in Prisma Client groups `findUnique()` queries with the same parameters and selection set. Each group is optimized into a single `findMany()`. #### Do I have to use the fluent API to enable batching of queries? It may seem counterintitive to use a `prisma.user.findUnique(...).posts()` query to return posts instead of `prisma.posts.findMany()` - particularly as the former results in two queries rather than one. -The **only** reason you need to use the fluent API (`user.findUnique(...).posts()`) to return posts is that the dataloader in Prisma Client batches `findUnique` queries and does not currently [batch `findMany` queries](https://github.com/prisma/prisma/issues/1477). +The **only** reason you need to use the fluent API (`user.findUnique(...).posts()`) to return posts is that the dataloader in Prisma Client batches `findUnique()` queries and does not currently [batch `findMany()` queries](https://github.com/prisma/prisma/issues/1477). -When the dataloader batches `findMany` queries, you no longer need to use `findUnique` with the fluent API in this way. +When the dataloader batches `findMany()` queries, you no longer need to use `findUnique()` with the fluent API in this way. ### n+1 in other contexts The n+1 problem is most commonly seen in a GraphQL context because you have to find a way to optimize a single query across multiple resolvers. However, you can just as easily introduce the n+1 problem by looping through results with `forEach` in your own code. -The following code results in n+1 queries - one `findMany` to get all users, and one `findMany` **per user** to get each user's posts: +The following code results in n+1 queries - one `findMany()` to get all users, and one `findMany()` **per user** to get each user's posts: @@ -326,10 +326,10 @@ SELECT "public"."Post"."id", "public"."Post"."createdAt", "public"."Post"."updat It is generally more performant to read and write large amounts of data in bulk - for example, inserting 50,000 records in batches of 1000 rather than as 50,000 separate inserts. Prisma Client supports the following bulk queries: -- [`createMany`](/orm/reference/prisma-client-reference#createmany) -- [`deleteMany`](/orm/reference/prisma-client-reference#deletemany) -- [`updateMany`](/orm/reference/prisma-client-reference#updatemany) -- [`findMany`](/orm/reference/prisma-client-reference#findmany) +- [`createMany()`](/orm/reference/prisma-client-reference#createmany) +- [`deleteMany()`](/orm/reference/prisma-client-reference#deletemany) +- [`updateMany()`](/orm/reference/prisma-client-reference#updatemany) +- [`findMany()`](/orm/reference/prisma-client-reference#findmany) ## Using select to limit number of columns returned @@ -338,6 +338,6 @@ Using `select` to limit the number of columns that are returned is **unlikely to - Tables with a large number of columns - Large columns that are stored in a separate location on disk rather than a row, which results in an additional disk read -Furthermore, if you have a mature product with well established query patterns and finely tuned indexes, selecting a specific subset of fields may be beneficial as it avoids reading data from disk. However, in most cases, this level of performance tuning is only necessary at a certain scale. +Furthermore, if you have a mature product with well-established query patterns and finely tuned indexes, selecting a specific subset of fields may be beneficial as it avoids reading data from disk. However, in most cases, this level of performance tuning is only necessary at a certain scale.