92 lines
1.9 KiB
Markdown
92 lines
1.9 KiB
Markdown
# Index Strategy Guide
|
|
|
|
## When to Add Indexes
|
|
|
|
Add `@@index` for fields that are:
|
|
|
|
- Frequently used in where clauses
|
|
- Used for sorting (orderBy)
|
|
- Foreign keys with frequent joins
|
|
- Composite conditions used together
|
|
|
|
## Single-Field Indexes
|
|
|
|
```prisma
|
|
model User {
|
|
id Int @id @default(autoincrement())
|
|
email String @unique
|
|
createdAt DateTime @default(now())
|
|
status String
|
|
|
|
@@index([createdAt])
|
|
@@index([status])
|
|
}
|
|
```
|
|
|
|
**Use Case:**
|
|
|
|
```typescript
|
|
await prisma.user.findMany({
|
|
where: { status: 'active' },
|
|
orderBy: { createdAt: 'desc' },
|
|
take: 20
|
|
})
|
|
```
|
|
|
|
Both status filter and createdAt sort benefit from indexes.
|
|
|
|
## Composite Indexes
|
|
|
|
```prisma
|
|
model Order {
|
|
id Int @id @default(autoincrement())
|
|
userId Int
|
|
status String
|
|
createdAt DateTime @default(now())
|
|
totalCents Int
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
|
|
@@index([userId, status])
|
|
@@index([status, createdAt])
|
|
}
|
|
```
|
|
|
|
**Composite Index Rules:**
|
|
|
|
1. Order matters: [userId, status] helps queries filtering by userId, or userId + status
|
|
2. Does NOT help queries filtering only by status
|
|
3. Most selective field should come first
|
|
4. Match your most common query patterns
|
|
|
|
**Use Case:**
|
|
|
|
```typescript
|
|
await prisma.order.findMany({
|
|
where: {
|
|
userId: 123,
|
|
status: 'pending'
|
|
},
|
|
orderBy: { createdAt: 'desc' }
|
|
})
|
|
```
|
|
|
|
First index [userId, status] optimizes the where clause.
|
|
Second index [status, createdAt] would help if querying by status alone with date sorting.
|
|
|
|
## Index Trade-offs
|
|
|
|
**Benefits:**
|
|
|
|
- Faster read queries (10-100x improvement on large tables)
|
|
- Required for efficient sorting and filtering
|
|
- Essential for foreign key performance
|
|
|
|
**Costs:**
|
|
|
|
- Slower writes (insert/update/delete must update indexes)
|
|
- Storage overhead (5-20% per index)
|
|
- Diminishing returns beyond 5-7 indexes per table
|
|
|
|
**Rule:** Only index fields actually used in queries. Remove unused indexes.
|