Files
gh-djankies-claude-configs-…/skills/optimizing-query-performance/references/batch-operations.md
2025-11-29 18:22:25 +08:00

94 lines
1.7 KiB
Markdown

# Batch Operations Guide
## createMany vs Loop
**SLOW (N database round-trips):**
```typescript
for (const userData of users) {
await prisma.user.create({ data: userData })
}
```
**FAST (1 database round-trip):**
```typescript
await prisma.user.createMany({
data: users,
skipDuplicates: true
})
```
**Performance Gain:** 50-100x faster for 1000+ records.
**Limitations:**
- createMany does NOT return created records
- Does NOT trigger middleware or relation cascades
- skipDuplicates skips on unique constraint violations (no error)
## Batch Updates
**SLOW:**
```typescript
for (const id of orderIds) {
await prisma.order.update({
where: { id },
data: { status: 'shipped' }
})
}
```
**FAST:**
```typescript
await prisma.order.updateMany({
where: { id: { in: orderIds } },
data: { status: 'shipped' }
})
```
**Note:** updateMany returns count, not records.
## Batch with Transactions
When you need returned records or relation handling:
```typescript
await prisma.$transaction(
users.map(userData =>
prisma.user.create({ data: userData })
)
)
```
**Use Case:** Creating related records where you need IDs for subsequent operations.
**Trade-off:** Slower than createMany but supports relations and returns records.
## Batch Size Considerations
For very large datasets (100k+ records), chunk into batches:
```typescript
const BATCH_SIZE = 1000
for (let i = 0; i < records.length; i += BATCH_SIZE) {
const batch = records.slice(i, i + BATCH_SIZE)
await prisma.record.createMany({
data: batch,
skipDuplicates: true
})
console.log(`Processed ${Math.min(i + BATCH_SIZE, records.length)}/${records.length}`)
}
```
**Benefits:**
- Progress visibility
- Memory efficiency
- Failure isolation (one batch fails, others succeed)