← Назад к вопросам

Какие знаешь индексы?

2.0 Middle🔥 181 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Индексы в базах данных

Индекс — это структура данных, которая ускоряет поиск записей в таблице. Думай о нём как об указателе в оглавлении книги: вместо чтения всех страниц, ты идешь прямо на нужную страницу.

1. Primary Key Index

Primary Key (ПК) — уникальный индекс, однозначно идентифицирующий запись.

@Entity
@Table(name = "users")
public class User {
    @Id  // Primary Key
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String email;
}

// SQL
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255),
    email VARCHAR(255)
);

Характеристики:

  • Уникальность гарантирована
  • Автоматически создается индекс B-Tree
  • Используется для быстрого поиска по id
  • O(log n) время поиска

2. Unique Index

Уникальный индекс гарантирует, что все значения в столбце уникальны.

@Entity
public class User {
    @Id
    private Long id;
    
    @Column(unique = true)  // Unique Index
    private String email;
}

// SQL
CREATE UNIQUE INDEX idx_user_email ON users(email);

// Или
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255) UNIQUE
);

3. Composite Index (Составной индекс)

Индекс по нескольким столбцам. Порядок столбцов важен!

@Entity
@Table(indexes = {
    @Index(name = "idx_user_email_created", 
           columnList = "email, created_at")
})
public class User {
    private String email;
    private LocalDateTime createdAt;
}

// SQL
CREATE INDEX idx_user_email_created ON users(email, created_at);

// Запросы которые используют этот индекс:
// SELECT * FROM users WHERE email = 'john@example.com';
// SELECT * FROM users WHERE email = 'john@example.com' AND created_at > '2024-01-01';

// Это НЕ использует индекс (неверный порядок)
// SELECT * FROM users WHERE created_at > '2024-01-01';

4. Full-Text Index

Индекс для полнотекстового поиска. Используется для поиска слов в текстовых данных.

@Entity
@Table(name = "articles")
public class Article {
    @Id
    private Long id;
    
    private String title;
    private String content;
}

// SQL
CREATE FULLTEXT INDEX idx_article_search ON articles(title, content);

// Поиск
SELECT * FROM articles 
WHERE MATCH(title, content) AGAINST('Java Spring' IN BOOLEAN MODE);

5. Spatial Index

Индекс для географических координат. Используется для поиска по расстоянию.

// SQL
CREATE SPATIAL INDEX idx_location ON stores(location);

// Поиск магазинов в радиусе 5 км от точки
SELECT * FROM stores 
WHERE ST_Distance(location, ST_GeomFromText('POINT(55.7558 37.6173)')) < 5000;

6. Hash Index

Индекс на основе хеширования. Быстро для точных совпадений, но не для диапазонов.

// MySQL
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    email VARCHAR(255),
    INDEX idx_email_hash (email) USING HASH
);

// Быстро: = и IN
SELECT * FROM users WHERE email = 'john@example.com';

// Медленно: LIKE, <, >, BETWEEN
SELECT * FROM users WHERE email LIKE '%@gmail.com';

7. B-Tree Index (стандартный)

B-Tree — самый распространенный индекс. Сбалансированное дерево.

// SQL
CREATE INDEX idx_user_email ON users(email) USING BTREE;

// Эффективен для:
// - Точных совпадений
// - Диапазонных поисков
// - Сортировки (ORDER BY)
SELECT * FROM users WHERE email = 'john@example.com';
SELECT * FROM users WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
SELECT * FROM users ORDER BY email;

8. Index on Expression

Индекс по выражению, не по столбцу.

// PostgreSQL
CREATE INDEX idx_user_lower_email ON users(LOWER(email));

// Используется для case-insensitive поиска
SELECT * FROM users WHERE LOWER(email) = 'john@example.com';

9. Partial Index

Индекс только на часть таблицы (по условию).

// PostgreSQL
CREATE INDEX idx_active_users ON users(email) WHERE status = 'ACTIVE';

// Используется когда большая часть данных неактивна
SELECT * FROM users WHERE status = 'ACTIVE' AND email = 'john@example.com';

10. Covering Index

Индекс содержит все нужные данные, так что БД не нужно читать основную таблицу.

// Индекс со всеми необходимыми столбцами
CREATE INDEX idx_user_email_name ON users(email, name, age);

// Query, которому хватает индекса (Index-Only Scan)
SELECT name, age FROM users WHERE email = 'john@example.com';

11. Проблемы с индексами

// 1. Слишком много индексов замедляет INSERT/UPDATE/DELETE
@Entity
@Table(indexes = {
    @Index(columnList = "email"),
    @Index(columnList = "phone"),
    @Index(columnList = "created_at"),
    @Index(columnList = "updated_at"),
    // ... еще 10 индексов
})
public class User { }

// 2. Индекс может быть неиспользуемым
CREATE INDEX idx_unused ON users(old_column);
// Запросы редко используют old_column

// 3. Неправильный порядок в составном индексе
CREATE INDEX idx_bad ON users(created_at, email);
SELECT * FROM users WHERE email = 'john@example.com';  // Не использует индекс

12. Стратегия создания индексов

// 1. Индексируй столбцы в WHERE
SELECT * FROM users WHERE email = 'john@example.com';
// ✓ Нужен индекс на email

// 2. Индексируй столбцы в JOIN
SELECT * FROM users u JOIN orders o ON u.id = o.user_id;
// ✓ Нужен индекс на user_id в orders

// 3. Индексируй столбцы в ORDER BY
SELECT * FROM users ORDER BY created_at DESC;
// ✓ Нужен индекс на created_at

// 4. Не индексируй все подряд
// ✗ Каждый индекс замедляет INSERT/UPDATE

// 5. Используй EXPLAIN для анализа
EXPLAIN SELECT * FROM users WHERE email = 'john@example.com';

13. Сравнение индексов

ИндексСкорость поискаINSERT/UPDATEПрименение
Primary KeyO(log n)МедленнееИдентификация
UniqueO(log n)МедленнееУникальность
B-TreeO(log n)МедленнееОбщее назначение
HashO(1)МедленнееТочные совпадения
Full-TextO(n)МедленнееТекстовый поиск
SpatialO(log n)МедленнееГеографические данные

Итог

Индексы — это мощный инструмент для оптимизации производительности:

  • Primary Key/Unique — для уникальности
  • B-Tree — для большинства случаев
  • Composite — для запросов с несколькими условиями
  • Full-Text — для полнотекстового поиска
  • Partial — для оптимизации памяти

Помни: индексы ускоряют SELECT, но замедляют INSERT/UPDATE/DELETE. Используй их разумно!

Какие знаешь индексы? | PrepBro