prisma: MongoDB: `upsert()` fails on `update()` with relation when `notablescan: 1`
Bug description
Using MongoDB, the following error occurs when running an upsert and the document already exists:
PrismaClientUnknownRequestError:
Invalid `prisma.user.upsert()` invocation:
Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: RawDatabaseError { code: "unknown", message: "Command failed (NoQueryExecutionPlans): error processing query: ns=ninja-diary.projectsTree: $expr {$and: [{$in: [\"$ownerId\", {$const: [\"qGdWa0VNzHfW8GRaDxz5nfjPDRt1\"]}]}, {$or: [{$ne: [{$ifNull: [\"$ownerId\", {$const: null}]}, {$const: null}]}, {$eq: [\"$ownerId\", {$const: null}]}]}]}Sort: {}\nProj: { _id: true, ownerId: true }\nCollation: { locale: \"simple\" }\n planner returned error :: caused by :: No indexed plans available, and running with 'notablescan')" } })
at Object.request (/usr/app/node_modules/@prisma/client/runtime/index.js:45582:15)
at async PrismaClient._request (/usr/app/node_modules/@prisma/client/runtime/index.js:46405:18)
at async setSyncTimeForUser (/usr/app/src/features/sync/utils.ts:29:18)
at async /usr/app/src/features/sync/push.ts:19:5
at async Proxy._transactionWithCallback (/usr/app/node_modules/@prisma/client/runtime/index.js:46366:18)
at async push (/usr/app/src/features/sync/push.ts:15:3)
at async /usr/app/src/app.ts:442:7 {
clientVersion: '3.12.0'
}
How to reproduce
model User {
id String @id @map("_id") @db.String
name String
lastSync DateTime @updatedAt
projects Project[]
@@map("users")
}
model Project {
id String @id @map("_id") @db.String
name String
owner User @relation(fields: [ownerId], references: [id])
ownerId String @db.String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isDeleted Boolean @default(false)
@@index([ownerId])
@@index([createdAt])
@@index([updatedAt])
@@index([isDeleted])
@@map("projects")
}
Run this once:
await prisma.user.upsert({
where: { id: userId },
create: { id: userId, name: "foo" },
update: { name: "foo2" },
});
This will create the document, which works. Then run it a second time, which will execute the “update” part since the document exists. It now fails with the error above.
If I remove the relation from the schema (and only have a “dum” ownerId
field) the opertation works again.
Expected behavior
It should not fail
Prisma information
Prisma v3.12.0
mongoDB 4.4
model User {
id String @id @map("_id") @db.String
name String
lastSync DateTime @updatedAt
projects Project[]
@@map("users")
}
model Project {
id String @id @map("_id") @db.String
name String
owner User @relation(fields: [ownerId], references: [id])
ownerId String @db.String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isDeleted Boolean @default(false)
@@index([ownerId])
@@index([createdAt])
@@index([updatedAt])
@@index([isDeleted])
@@map("projects")
}
Run this once:
await prisma.user.upsert({
where: { id: userId },
create: { id: userId, name: "foo" },
update: { name: "foo2" },
});
Environment & setup
- OS: debian
- Database: MongoDB Atlas v4.4
- Node.js version: 16.13
Prisma Version
prisma : 3.12.0
@prisma/client : 3.12.0
Current platform : debian-openssl-1.1.x
Query Engine (Node-API) : libquery-engine 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/libquery_engine-debian-openssl-1.1.x.so.node)
Migration Engine : migration-engine-cli 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/migration-engine-debian-openssl-1.1.x)
Introspection Engine : introspection-core 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/introspection-engine-debian-openssl-1.1.x)
Format Binary : prisma-fmt 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/prisma-fmt-debian-openssl-1.1.x)
Default Engines Hash : 22b822189f46ef0dc5c5b503368d1bee01213980
Studio : 0.459.0
Preview Features : interactiveTransactions, extendedIndexes
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 3
- Comments: 35 (11 by maintainers)
This (using
in
) has just caused us an enormous ($$$) bill on mongodb atlas (serverless bills by usage), due to prisma running full table scans and ignoring indexes. I was shocked and disappointed to learn that this is known issue without a workaround. There should be a warning for everyone to not use prisma with mongodb currently.Is performance problem mentioned in Prisma documentation? Because this is a huge factor while choosing an ORM.
We’re encountering the same issue with ‘include’ after going to production. We were able to hack around it for now. However, we will likely migrate off of Prisma if a fix doesn’t come sometime soon which stinks since the DX has been amazing outside of the performance issues w/ mongodb.
This is extremely disappointing and a bit deceiving to hide from Prisma Mongo users. the fact a simple where _id in [] won’t use an index is shocking. We will be migrating off Prisma. and to think we were considering accelerate 😞
Yep, if I know before hand that bad performance means not using index and costing me 100x more then I wouldn’t have gone with Prisma. I would have used something like Mongoose instead.
I did some more investigating and the issue seems broader, as a lot of operations seem to cause a collection scan instead of using an index.
Specifically, I have found that using the
in
operator always causes an aggregation command that fails to use an index. For examplecauses a collection scan. I have confirmed this by running
explain
on theaggregate
command prisma ends up running (using query logging).I added a couple million objects to the collection, and running the
findMany
command takes over 300ms locally vs <5ms when using mongoDB driverMy recommendation is https://mikro-orm.io/. Haven’t used it with MongoDB, but with PG it was amazing. And of course migrating off MongoDB mid-term in most use-cases.
Is there an ETA on when the performance issues outlined in this issue and https://github.com/prisma/prisma/issues/14871 will be addressed ?
I was hoping for some improvement before I had to go to production, but that is looking less and less likely, so I am planning to replace prisma with mongoose in all our mongo-backed services.
Is there any chance for performance improvements within the next 1-2 months ?
@AndreasKarz the intention isn’t to run with
notablescan
in production, but to run with it in development to catch potential performance issues in development and add appropriate indexes before moving to production to ensure the fast running of queries.Simplified schema for further reproduction:
and script with query logging:
@janpio I am able to reproduce locally with mongo v5.0.6 and prisma
v3.13.0