Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Индексы в базах данных
Индекс — это структура данных, которая ускоряет поиск записей в таблице. Думай о нём как об указателе в оглавлении книги: вместо чтения всех страниц, ты идешь прямо на нужную страницу.
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 Key | O(log n) | Медленнее | Идентификация |
| Unique | O(log n) | Медленнее | Уникальность |
| B-Tree | O(log n) | Медленнее | Общее назначение |
| Hash | O(1) | Медленнее | Точные совпадения |
| Full-Text | O(n) | Медленнее | Текстовый поиск |
| Spatial | O(log n) | Медленнее | Географические данные |
Итог
Индексы — это мощный инструмент для оптимизации производительности:
- Primary Key/Unique — для уникальности
- B-Tree — для большинства случаев
- Composite — для запросов с несколькими условиями
- Full-Text — для полнотекстового поиска
- Partial — для оптимизации памяти
Помни: индексы ускоряют SELECT, но замедляют INSERT/UPDATE/DELETE. Используй их разумно!