Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(qe): implement relationLoadStrategy query argument #4601

Merged
merged 25 commits into from
Jan 9, 2024

Conversation

aqrln
Copy link
Member

@aqrln aqrln commented Dec 20, 2023

Implement per-query configuration of relation load strategy as described in https://www.notion.so/prismaio/Relation-load-strategy-API-013e3ba957a34d45b4de1b722ca6804d, particularly this section (Variant 1, only top level).

This allows to choose the relation load strategy for all relations in a single query.

Engine API:

query {
  findManyUser(relationLoadStrategy: join) {
    login
    posts { title }
  }
}

Client API:

await prisma.user.findMany({
  relationLoadStrategy: 'join', // or 'query'
  select: {
    login: true,
    posts: {
      title: true,
    },
  },
})

The new relationLoadStrategy argument is available in the following operations:

  • findMany
  • findFirst
  • findFirstOrThrow
  • findUnique
  • findUniqueOrThrow
  • create
  • update
  • delete
  • upsert

The argument is not available in the following operations:

  • aggregate
  • groupBy
  • createMany
  • updateMany
  • deleteMany

Tests are included for all operations in this PR.

Additionally, it must not be available in the count operation, which needs to be handled separately on the client side, because count is a synthetic operation that does not exist in the query schema and is not known to the engine, and its TS types are generated based on findMany args rather than aggregate that it translates to.

Next steps:

  • Finalize the Client integration PR
  • Implement the global setting

Part of https://github.com/prisma/team-orm/issues/703
Closes: https://github.com/prisma/team-orm/issues/801
Client PR: prisma/prisma#22483

Copy link
Contributor

github-actions bot commented Dec 20, 2023

WASM Size

Engine This PR Base branch Diff
WASM 2.744MiB 2.744MiB -709.000B
WASM (gzip) 1.006MiB 1.006MiB 63.000B

@aqrln aqrln self-assigned this Dec 20, 2023
@aqrln aqrln added this to the 5.8.0 milestone Dec 20, 2023
@aqrln aqrln force-pushed the feat-qe-implement-relationloadstrategy-api branch from 90cb9fa to 133f46f Compare December 20, 2023 17:02
Copy link

codspeed-hq bot commented Dec 20, 2023

CodSpeed Performance Report

Merging #4601 will not alter performance

Comparing feat-qe-implement-relationloadstrategy-api (d2f0998) with main (fecfd2f)

Summary

✅ 11 untouched benchmarks

Copy link
Contributor

github-actions bot commented Dec 20, 2023

✅ WASM query-engine: no benchmarks have regressed

Full benchmark report
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/bench?schema=imdb_bench&sslmode=disable" \
node --experimental-wasm-modules query-engine/driver-adapters/executor/dist/bench.mjs
cpu: AMD EPYC 7763 64-Core Processor
runtime: node v18.19.0 (x64-linux)

benchmark                   time (avg)             (min … max)       p75       p99      p995
-------------------------------------------------------------- -----------------------------
• movies.findMany() (all - 25000)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline  310.97 ms/iter (306.45 ms … 317.13 ms) 312.45 ms 317.13 ms 317.13 ms
Web Assembly: Latest     312.7 ms/iter (306.69 ms … 320.73 ms) 315.06 ms 320.73 ms 320.73 ms
Web Assembly: Current   312.39 ms/iter (307.14 ms … 319.12 ms) 314.25 ms 319.12 ms 319.12 ms
Node API: Current       233.01 ms/iter (222.07 ms … 251.74 ms) 233.94 ms 251.74 ms 251.74 ms

summary for movies.findMany() (all - 25000)
  Web Assembly: Current
   1.34x slower than Node API: Current
   1x faster than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movies.findMany({ take: 2000 })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   12.57 ms/iter    (11.91 ms … 17.2 ms)  12.58 ms   17.2 ms   17.2 ms
Web Assembly: Latest     12.67 ms/iter   (12.22 ms … 17.93 ms)  12.57 ms  17.93 ms  17.93 ms
Web Assembly: Current    12.65 ms/iter   (11.93 ms … 16.27 ms)  12.66 ms  16.27 ms  16.27 ms
Node API: Current         9.55 ms/iter    (9.16 ms … 14.39 ms)    9.5 ms  14.39 ms  14.39 ms

summary for movies.findMany({ take: 2000 })
  Web Assembly: Current
   1.33x slower than Node API: Current
   1.01x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movies.findMany({ where: {...}, take: 2000 })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline    2.05 ms/iter     (1.85 ms … 3.48 ms)   2.01 ms    3.4 ms   3.43 ms
Web Assembly: Latest      2.09 ms/iter     (1.85 ms … 3.41 ms)   2.07 ms   3.39 ms   3.41 ms
Web Assembly: Current     2.06 ms/iter     (1.86 ms … 3.51 ms)   1.99 ms   3.39 ms   3.41 ms
Node API: Current          1.6 ms/iter     (1.51 ms … 2.05 ms)   1.61 ms   1.89 ms   2.05 ms

summary for movies.findMany({ where: {...}, take: 2000 })
  Web Assembly: Current
   1.29x slower than Node API: Current
   1.01x slower than Web Assembly: Baseline
   1.01x faster than Web Assembly: Latest

• movies.findMany({ include: { cast: true } take: 2000 }) (m2m)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   12.52 ms/iter   (11.99 ms … 14.39 ms)   12.6 ms  14.39 ms  14.39 ms
Web Assembly: Latest     12.56 ms/iter   (12.28 ms … 13.06 ms)   12.7 ms  13.06 ms  13.06 ms
Web Assembly: Current    12.53 ms/iter   (12.07 ms … 13.01 ms)  12.67 ms  13.01 ms  13.01 ms
Node API: Current         9.91 ms/iter     (9.24 ms … 14.9 ms)   9.84 ms   14.9 ms   14.9 ms

summary for movies.findMany({ include: { cast: true } take: 2000 }) (m2m)
  Web Assembly: Current
   1.26x slower than Node API: Current
   1x faster than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movies.findMany({ where: {...}, include: { cast: true } take: 2000 }) (m2m)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline    1.97 ms/iter     (1.85 ms … 3.09 ms)   1.94 ms   2.94 ms   3.04 ms
Web Assembly: Latest      1.96 ms/iter     (1.85 ms … 4.32 ms)   1.93 ms   3.05 ms   3.12 ms
Web Assembly: Current     1.95 ms/iter     (1.85 ms … 3.12 ms)   1.93 ms   2.82 ms   3.11 ms
Node API: Current          1.6 ms/iter     (1.52 ms … 1.91 ms)   1.62 ms   1.87 ms   1.89 ms

summary for movies.findMany({ where: {...}, include: { cast: true } take: 2000 }) (m2m)
  Web Assembly: Current
   1.22x slower than Node API: Current
   1x faster than Web Assembly: Latest
   1.01x faster than Web Assembly: Baseline

• movies.findMany({ take: 2000, include: { cast: { include: { person: true } } } })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   12.65 ms/iter   (12.29 ms … 13.48 ms)  12.75 ms  13.48 ms  13.48 ms
Web Assembly: Latest     12.78 ms/iter    (12.55 ms … 15.2 ms)   12.8 ms   15.2 ms   15.2 ms
Web Assembly: Current    12.66 ms/iter   (12.17 ms … 14.33 ms)  12.78 ms  14.33 ms  14.33 ms
Node API: Current         10.2 ms/iter    (9.26 ms … 14.24 ms)  10.21 ms  14.24 ms  14.24 ms

summary for movies.findMany({ take: 2000, include: { cast: { include: { person: true } } } })
  Web Assembly: Current
   1.24x slower than Node API: Current
   1x faster than Web Assembly: Baseline
   1.01x faster than Web Assembly: Latest

• movie.findMany({ where: { ... }, take: 2000, include: { cast: { include: { person: true } } } })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline    1.93 ms/iter     (1.83 ms … 3.22 ms)   1.93 ms   2.52 ms   2.61 ms
Web Assembly: Latest      1.95 ms/iter     (1.82 ms … 2.94 ms)   1.93 ms   2.87 ms   2.88 ms
Web Assembly: Current     1.92 ms/iter     (1.83 ms … 2.45 ms)   1.92 ms   2.44 ms   2.44 ms
Node API: Current         1.59 ms/iter     (1.49 ms … 2.06 ms)   1.61 ms   1.87 ms   2.04 ms

summary for movie.findMany({ where: { ... }, take: 2000, include: { cast: { include: { person: true } } } })
  Web Assembly: Current
   1.2x slower than Node API: Current
   1.01x faster than Web Assembly: Baseline
   1.02x faster than Web Assembly: Latest

• movie.findMany({ where: { reviews: { author: { ... } }, take: 100 }) (to-many -> to-one)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline  931.88 µs/iter   (869.54 µs … 1.68 ms) 931.12 µs   1.38 ms   1.47 ms
Web Assembly: Latest    923.49 µs/iter   (852.98 µs … 1.58 ms) 918.88 µs   1.49 ms   1.55 ms
Web Assembly: Current   939.29 µs/iter   (863.25 µs … 1.78 ms) 929.45 µs   1.51 ms   1.59 ms
Node API: Current        860.9 µs/iter    (764.3 µs … 1.09 ms) 878.55 µs   1.02 ms   1.05 ms

summary for movie.findMany({ where: { reviews: { author: { ... } }, take: 100 }) (to-many -> to-one)
  Web Assembly: Current
   1.09x slower than Node API: Current
   1.02x slower than Web Assembly: Latest
   1.01x slower than Web Assembly: Baseline

• movie.findMany({ where: { cast: { person: { ... } }, take: 100 }) (m2m -> to-one)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline  976.04 µs/iter    (865.4 µs … 1.95 ms) 940.02 µs   1.68 ms   1.71 ms
Web Assembly: Latest    915.76 µs/iter   (861.63 µs … 1.43 ms) 917.97 µs   1.32 ms   1.39 ms
Web Assembly: Current   918.14 µs/iter   (866.87 µs … 1.44 ms)    920 µs   1.29 ms    1.4 ms
Node API: Current       861.33 µs/iter   (774.93 µs … 1.11 ms) 877.28 µs   1.02 ms   1.07 ms

summary for movie.findMany({ where: { cast: { person: { ... } }, take: 100 }) (m2m -> to-one)
  Web Assembly: Current
   1.07x slower than Node API: Current
   1x faster than Web Assembly: Latest
   1.06x faster than Web Assembly: Baseline

After changes in d2f0998

aqrln added a commit to prisma/prisma that referenced this pull request Dec 20, 2023
aqrln added a commit to prisma/prisma that referenced this pull request Dec 20, 2023
@aqrln aqrln changed the title feat(qe): implement relationLoadStrategy API feat(qe): implement relationLoadStrategy argument Dec 22, 2023
@aqrln aqrln changed the title feat(qe): implement relationLoadStrategy argument feat(qe): implement relationLoadStrategy query argument Dec 22, 2023
@aqrln aqrln marked this pull request as ready for review December 23, 2023 00:22
@aqrln aqrln requested a review from a team as a code owner December 23, 2023 00:22
@aqrln aqrln requested review from miguelff, jkomyno and Weakky and removed request for a team and jkomyno December 23, 2023 00:22
Copy link
Contributor

@Weakky Weakky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, nice work 💯

@aqrln aqrln force-pushed the feat-qe-implement-relationloadstrategy-api branch from 7d8c992 to 42211f0 Compare January 8, 2024 10:16
@@ -54,7 +54,7 @@ fi
# Check if the system has engineer installed, if not, use a local copy.
if ! type "engineer" &> /dev/null; then
# Setup Prisma engine build & test tool (engineer).
curl --fail -sSL "https://prisma-engineer.s3-eu-west-1.amazonaws.com/1.65/latest/$OS/engineer.gz" --output engineer.gz
curl --fail -sSL "https://prisma-engineer.s3-eu-west-1.amazonaws.com/1.66/latest/$OS/engineer.gz" --output engineer.gz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional in this PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -228,7 +228,7 @@ services:

mysql-5-6:
image: mysql:5.6.50
command: mysqld
command: mysqld --table_definition_cache=2000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for this in this PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, too many tests broke MySQL 5.6

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was fixed in MySQL 5.7, only 5.1 to 5.6 had this issue.

aqrln added a commit to prisma/prisma that referenced this pull request Jan 8, 2024
@@ -258,6 +259,7 @@ pub(crate) fn get_relation_load_strategy(
ReadQuery::RelatedRecordsQuery(q) => q.has_cursor() || q.has_distinct() || q.has_aggregation_selections(),
_ => false,
})
&& requested_strategy != Some(RelationLoadStrategy::Query)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: (maybe that does not change much), it would be "faster" to check for this condition earlier (maybe in second position?).
The other conditions would not be evaluated then when RelationLoadStrategy is set to query

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to tell if it matters without looking at the generated code but yeah it makes sense even from just from stylistic perspective, I think the code reads a bit more naturally with this check earlier. We need to get this merged now as we don't have much time waiting on CI before the release but I can change it in a follow up PR.

@aqrln aqrln merged commit 0a83d85 into main Jan 9, 2024
140 checks passed
@aqrln aqrln deleted the feat-qe-implement-relationloadstrategy-api branch January 9, 2024 12:13
aqrln added a commit to prisma/prisma that referenced this pull request Jan 9, 2024
Client-side counterpart of <prisma/prisma-engines#4601>.

* Ensure `count` operation types are correct by filtering out the `relationLoadStrategy` argument.
* Add tests for everything.
* Update existing tests.

Part of: prisma/team-orm#703
Closes: prisma/team-orm#801
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants