A partial index is a powerful feature that allows you to create an index only on a subset of rows of the given table based on some conditions. Thus reducing the size of the index and optimizing queries. Its syntax is as follows (in PostgreSQL):
It is often helpful when you want to avoid indexing on some values that are very frequent in the db but not queried upon. For example, to prevent indexing graduated students in a student table.
or to exclude unavailable products from an index in a product table
Recently, I found them very useful when implementing soft delete. Say you are working to build a social media platform, and your user table looks like this:
You also have a unique index on the username to enforce unique usernames.
Now you decide to soft-delete users (mark a user as deleted instead of actually deleting them from the DB), so you naively add a new field state
. Whenever a user is deleted, their state
is set to DELETED
.
But later, you realize a big flaw with this approach. Because of the unique index, you won’t be able to reclaim usernames from deleted users! To fix it, you may be tempted to create a unique index on username
and state
. But even this unique index will break when you try to delete a user when another user with the same username was deleted earlier.
So, what to do now? The answer is simple. Just drop the unique constraint and add a partial unique index as follows:
And voilà, the problem is solved.