Skip to main content

Command Palette

Search for a command to run...

Understanding Indexes Before Learning Index Types

Updated
3 min read
Y
Senior Ruby on Rails Engineer sharing practical insights on Rails, React, system design, performance optimization,. My goal is to simplify complex concepts through real-world examples and hands-on experiences.

Before diving into different types of indexes, let's understand why indexes are needed.

Imagine a library with 100,000 books.

If someone asks for a book named "Clean Code", there are two ways to find it:

Without an Index

You start from the first shelf and check every book one by one until you find the required book.

This approach is similar to a Sequential Scan in PostgreSQL.

SELECT * FROM books
WHERE title = 'Clean Code';

PostgreSQL may need to scan every row in the table to find matching records.

As the table grows from thousands to millions of rows, query performance degrades significantly.

With an Index

Now imagine the library has a catalog that stores:

Clean Code      → Shelf A12
The Pragmatic Programmer → Shelf B03
Refactoring     → Shelf C08

Instead of checking every book, you first look at the catalog and immediately jump to the correct shelf.

This catalog is similar to a database index.

An index stores selected column values in a structure that allows PostgreSQL to locate rows much faster than scanning the entire table.

Why Not Index Every Column?

A common beginner question is:

If indexes make queries faster, why not create indexes everywhere?

Indexes improve read performance, but they come with a cost.

Whenever data changes, PostgreSQL must update both:

  1. The table data

  2. Every related index

For example:

User.create!(email: "john@example.com")

If the users table has 10 indexes, PostgreSQL must update all 10 indexes during the insert operation.

This means:

  • More storage usage

  • Slower INSERT operations

  • Slower UPDATE operations

  • Slower DELETE operations

Because of this trade-off, indexes should be added only for queries that are frequently executed and benefit from faster lookups.

How PostgreSQL Uses an Index

Suppose we have:

add_index :users, :email

And run:

SELECT *
FROM users
WHERE email = 'john@example.com';

Without an index:

Seq Scan on users

With an index:

Index Scan using index_users_on_email

The database can jump directly to matching records instead of examining every row.

A Simple Rule

Create an index when a column is frequently used in:

  • WHERE clauses

  • JOIN conditions

  • ORDER BY clauses

  • GROUP BY clauses

Examples:

User.find_by(email: email)

Order.where(user_id: current_user.id)

Product.order(created_at: :desc)

Lead.where(status: "active")

These are strong candidates for indexing.

How to Verify an Index Is Being Used

Never assume PostgreSQL is using your index.

Use:

EXPLAIN ANALYZE
SELECT *
FROM users
WHERE email = 'john@example.com';

Look for:

Index Scan

instead of:

Seq Scan

This confirms PostgreSQL is benefiting from the index.

Understanding these fundamentals makes it much easier to choose the right indexing strategy, whether it is a simple B-Tree index, a composite index, a GIN index for JSONB data, or a BRIN index for massive datasets.