Automatically create an index on `@relation` by default, add new option for disabling - for `referentialIntegrity/relationMode = prisma`
See original GitHub issueThe Problem
Right now, there are two ways of ensuring referential integrity within Prisma. One is using foreign keys, which under the hood create a foreign key by default in the schema. When you switch to using referentialIntegrity = prisma
in the Prisma configuration, the onus then is on the user to remember to create a separate @index
in the schema to use with the referenced column. Folks who are new to databases or not as knowledgeable may forget this step, leading to slower queries and a worse experience overall.
The Proposed Solution
To address this, I’d like to propose a couple of changes.
First, when using @relation
, there will be an index automatically created on the relevant column. For the referential integrity using foreign keys, this will already happen by default, so that behavior stays the same. But this will needed to be added for use with the prisma
referential integrity.
Second, I’d like to propose the addition of a boolean index:
input to the @relation
function. This will be used for disabling the creation of indexes when using @relation
, but by default, the index
value will be true
. This transforms the use of the function to look something like this:
Without an indexed relationship
model Post {
author User @relation(fields: [authorId], references: [id], index: false)
authorId Int @unique
title String
published Boolean @default(false)
@@index([authorId])
}
model User {
id Int @id @default(autoincrement())
email String? @unique
name String
Post Post[]
}
This will create a relationship between Post
and User
, but the authorId
will not be indexed.
My line of thinking around this is that ORMs in various other frameworks, such as ActiveRecord and Django, automatically create indexes on foreign key relations (even if foreign key constraints are disabled), unless the user explicitly disables them for that specific field, rather than defining the index for a foreign key separately.
With an indexed relationship
model Post {
author User @relation(fields: [authorId], references: [id], index: true)
authorId Int
title String
published Boolean @default(false)
}
model User {
id Int @id @default(autoincrement())
email String? @unique
name String
Post Post[]
}
In this case, the authorId
will be indexed and you will have this relationship between the two.
Benefits
I think this will overall lead to be a better user experience when using Prisma, especially with serverless solutions such as PlanetScale. Users of all skill levels will not have to wonder why their queries are running slowly, as by default, they will have an index on the columns used for referential integrity. Additionally, if they don’t actually need to use this index, it will be easy to disable the index by adding index: false
to the relation itself.
Downsides
This will change the default behavior for users using Prisma, as indexes by default do take up more space. But on the other hand, using up more space by default and having faster queries and disabling unnecessary indexes sounds more ideal than having slower queries from the jump and not knowing why. Additionally, this will introduce a new way of defining indexes into Prisma, and if users want to make something like a composite index, they’d probably have to do something like this:
model Post {
author User @relation(fields: [authorId], references: [id], index: false)
authorId Int
title String
published Boolean @default(false)
@@index([authorId])
}
On the other hand, I can also see the benefits of this, because with situations like foreign key constraints automatically creating indexes under the hood, explicitly disabling the indexes with index: false
and creating the unique
constraint or a different index may be more beneficial.
Open Questions
- How should the
index
be created when defined on arelation
? I was thinking that maybe the attributes defined infields
could be used as the source of truth for what the index is, given they are what are defining the relationship. - Should we add for an optional
unique
flag to be added to the relation to make sure that the created index for a relation is unique as well?
Related
Issue Analytics
- State:
- Created 2 years ago
- Reactions:29
- Comments:15 (9 by maintainers)
Top GitHub Comments
I’m fully in support of adding this (I’m a Planetscale user)
Nice! Just upgraded, and was pointed out two such indexes that I’d missed adding in our 1,500 line
schema.prisma
file.Huge help to have this validation warning!