Skip to main content

Using indexes

Indexes are data structures that allow the database to locate rows without scanning the entire table. Without an index, a query must examine every row to find matches. With an index, the database can jump directly to the relevant rows — dramatically reducing the number of rows examined.

Indexes accelerate read operations but add overhead to writes (inserts, updates, deletes) since the index must be kept in sync, so they should be created carefully and only when needed.

Good candidates for indexes are columns frequently used in WHERE clauses, joins, and sorting. When more than one column is used as a filter, it might make sense to create a composite index, however bear in mind that column order matters — place the most selective (most unique values) columns first.

Analyzing query performance

Most databases let you inspect how a query is being executed, which is called an execution plan. Understanding such a plan helps you identify missing indexes and optimize how a query is constructed by comparing various ways of fetching the same data.

CockroachDB

Use EXPLAIN ANALYZE (same syntax as PostgreSQL):

EXPLAIN ANALYZE SELECT * FROM "user" WHERE "firstName" = 'Timber';

Look for full scan (no index) vs scan with a specific index name.

Learn more

Defining indexes in TypeORM

TypeORM supports creating indexes on table columns using the @Index decorator.

import { Entity, PrimaryGeneratedColumn, Column, Index } from "typeorm"

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number

@Column()
@Index()
email: string

@Column()
firstName: string
}

For a comprehensive overview of different index types (unique, spatial, fulltext, concurrent, and more), read the Indexes guide.

Proper indexing is often the single biggest performance improvement you can make — start by analyzing your slowest queries with the execution plan tools above, then add indexes where they matter most.