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

perf: remove select before deleteMany #4249

Merged
merged 3 commits into from
Sep 29, 2023
Merged

Conversation

Weakky
Copy link
Member

@Weakky Weakky commented Sep 18, 2023

Overview

fixes prisma/prisma#7232
fixes prisma/prisma#8239
fixes https://github.com/prisma/prisma-private/issues/217
fixes prisma/prisma#15085
fixes prisma/prisma#19950

On SQL connectors

We used to perform two SELECTs to fetch the ids to delete before passing these ids to the actual delete statement. This was causing several issues:

  1. The SELECTs were superfluous
  2. A transaction was required
  3. The delete operation could mess up index usage because it wouldn't only be using the filter but also an IN clause with all the ids fetched by the SELECT. (cf issue above)

This PR fixes the problem by removing the SELECT altogether (on a top-level deleteMany). This makes it possible to remove the transaction entirely.

On MongoDB

We used to have duplicate selects before the delete. This is now fixed by passing the fetched ids down to the delete node in the graph. I'm unsure whether we can get rid of the select before the delete on Mongo because:

  1. Joins aren't supported
  2. More operators might not be supported and I need to verify. For now, we just solved the duplicate select issue.

SQL Diff

model Trade {
  id         Int
  marketId   Int      @db.SmallInt
  @@id([marketId, id])
}
mutation {
  deleteManyTrade(where: { marketId: 1, id: { lte: 10 } }) { count }
}
-- before
BEGIN
SELECT id FROM "Trade" WHERE marketId = 1 AND id <= 10
SELECT id FROM "Trade" WHERE marketId = 1 AND id <= 10 AND id IN (<...select ids>)
DELETE FROM "Trade" WHERE id IN (<...select ids>) AND marketId = 1 AND id <= 10
COMMIT

-- after
DELETE FROM "Trade" WHERE marketId = 1 AND id <= 10;

Benchmark

Datamodel:

model User {
  id Int @id @default(autoincrement())
  name String
}

Dataset size: 200k users

Query:

mutation {
  deleteManyUser(where: { id: {gt: 50000 }, name: { lt: { 'g' } } } { count }
}

Result:

Before: 387.930 ± 42.506ms
After: 62.992 ± 21.071ms

@Weakky Weakky requested a review from a team as a code owner September 18, 2023 16:13
@Weakky Weakky force-pushed the perf/delete-many-redundant-select branch from 9da1439 to 5cdeb3b Compare September 18, 2023 16:15
@codspeed-hq
Copy link

codspeed-hq bot commented Sep 18, 2023

CodSpeed Performance Report

Merging #4249 will improve performances by 5.67%

Comparing perf/delete-many-redundant-select (1fa92cb) with main (5c9823b)

Summary

⚡ 1 improvements
✅ 10 untouched benchmarks

Benchmarks breakdown

Benchmark main perf/delete-many-redundant-select Change
large_read 7.7 ms 7.3 ms +5.67%

@Weakky Weakky added this to the 5.4.0 milestone Sep 27, 2023
@Weakky Weakky force-pushed the perf/delete-many-redundant-select branch from 6a0058c to 634e685 Compare September 27, 2023 16:02
Copy link
Contributor

@miguelff miguelff left a comment

Choose a reason for hiding this comment

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

Outstanding!

@@ -62,31 +63,45 @@ pub fn delete_many_records(
model: Model,
mut field: ParsedField<'_>,
) -> QueryGraphBuilderResult<()> {
graph.flag_transactional();
Copy link
Contributor

Choose a reason for hiding this comment

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

📉

@miguelff miguelff merged commit 18f3e40 into main Sep 29, 2023
30 of 38 checks passed
@miguelff miguelff deleted the perf/delete-many-redundant-select branch September 29, 2023 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants