Efficiently create many records
See original GitHub issueWe need a way to efficiently insert many rows of data.
For small amounts of data, a simple batch API might be sufficient, as the database can handle all the operations in a short time. This could either be exposed through operations similar to our nested create
API as described below, or through a new Batch API as described in https://github.com/prisma/prisma-client-js/issues/667.
For large amounts of data, we need to support breaking the large number of create operations into smaller batches. In order to optimise throughput, you need to balance two things: provide large enough work packages such that network latency doesn’t dominate the actual work, and keep the work packages small enough to not overwhelm the database. This could be exposed through a batch API with configurable batch size, or through a streaming API with buffering support.
Original issue
I think is quite common the need of having to create or upsert many records on a database at the same time, at least is a feature I see in many other ORMs.
Right now is posible to create many records using a nested write like this
const newUser: User = await photon.users.create({
data: {
email: 'alice@prisma.io',
posts: {
create: [
{ title: 'Join the Prisma Slack on https://slack.prisma.io' },
{ title: 'Follow Prisma on Twitter' },
],
},
},
})
But sometimes you just want to create many records, in this case the only thing I managed to find to accomplish is by doing this
const newPosts = [
{ id: 1, title: 'Join the Prisma Slack on https://slack.prisma.io' },
{ id: 2, title: 'Follow Prisma on Twitter' },
];
// create
const createManyPosts = newPosts.map((post) =>
photon.posts.create({
data: post,
}),
);
Promise.all(createManyPosts);
// upsert
const upsertManyPosts = newPosts.map((post) =>
photon.posts.upsert({
where: { id: post.id },
create: post,
update: post,
}),
);
Promise.all(upsertManyPosts);
This with 2 records works fine, but as soon as you need to create 1000 doesn’t seems right to fire 1000 promises.
Maybe I’m missing something and there is a good reason for a feature like this to not be available, or maybe is already planned to be added in future releases?
I think prisma2 is awesome! Thank you all very much for this product 😃 it’s totally an step forward.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:129
- Comments:46 (17 by maintainers)
Wanted to add my vote to this ticket. This is currently quite a deal-breaker for us. Our app isn’t huge, but at one point it requires creating around 1000 rows in a table. It would be great if this was possible via Photon.
@timsuchanek any idea on timelines for this? I guess it would be sometime after Prisma2 GA?
Hey folks, we’ve started designing this feature.
Please have a read through the proposal and let us know what you think! Also feel free to schedule time with me to chat about this proposal.
Proposal
Database Support
Operations
Bulk Create
Example
Idempotent Creates
If you try creating many records at once, the whole operation can fail if there are any constraint violations. The
skipDuplicates
key helps avoid this.When
skipDuplicates: true
, if a record already exists it, the record will be ignored. This feature is only supported by databases that support INSERT ON CONFLICT DO NOTHING.Currently, Microsoft’s SQL Server does not fully support this feature, so we’ve disabled
skipDuplicates
.Nested Create Many
create
andupdate
operations.create
withcreateMany
ExampleOne important distinction is that we will still continue to support a nested
create: [...]
. This is functionally similar tocreateMany: [...]
, but has a few subtle differences:create: [...]
creates records one query at a timecreate: [...]
supports nesting additional relationscreate: [...]
cannot skip over duplicate recordscreate: [...]
supports has-many and many-to-many relationscreateMany: [...]
inserts all the records in one querycreateMany: [...]
does not support nesting additional relationsaddressId: 10
)createMany: [...]
can skip over duplicate recordscreateMany: [...]
supports has-many but not many-to-many relationsLimitations
@default(autoincrement())
Out of Scope
upsert
are not applicable to a many operation.createMany
.RETURNING
natively.createMany
, callfindMany
after.select
andinclude
options not supportedselect
andinclude
operations do not apply.create
,connect
,connectOrCreate
data
won’t allow nested relations to be created or connected.prisma.createMany([post, update])
)COPY IN
)FAQ
How do I get the records back after a createMany?
To get the records back, you can use a
findMany
after yourcreateMany
. This will require you to findMany by a unique field in the record or precompute your IDs.So for the following Prisma Schema:
You can pre-compute the IDs and search by them after: