question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Automatically create an index on `@relation` by default, add new option for disabling - for `referentialIntegrity/relationMode = prisma`

See original GitHub issue

The 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 a relation? I was thinking that maybe the attributes defined in fields 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:open
  • Created 2 years ago
  • Reactions:29
  • Comments:15 (9 by maintainers)

github_iconTop GitHub Comments

12reactions
flybayercommented, Dec 7, 2021

I’m fully in support of adding this (I’m a Planetscale user)

5reactions
michaelhayscommented, Nov 30, 2022

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!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Indexes - Prisma
Prisma Migrate is able to create constraints and indexes with the length argument if specified in your data model. This means that you...
Read more >
How to configure indexes in Prisma - LogRocket Blog
Configuring indexes in SQL databases. By now, we know that indexes can be added by using the @@index attribute in Prisma. But, since ......
Read more >
Creating Indexes
The database enforces UNIQUE integrity constraints by automatically defining a unique index on the unique key. This is discussed in the following section....
Read more >
sql server - Does a foreign key automatically create an index?
A foreign key is a constraint, a relationship between two tables - that has nothing to do with an index per se. But...
Read more >
Elasticsearch Mapping Basics & Examples (After Create Index)
What custom rules should be set to update new field types automatically as they are added (e.g., the dynamic mapping type, which we...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found