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

Какие поля будешь индексировать для оптимизации запроса

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

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

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

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

Какие поля будешь индексировать для оптимизации запроса?

Выбор полей для индексирования — это критический аспект оптимизации производительности БД. Правильная стратегия индексирования может улучшить скорость запросов в разы, но неправильная может замедлить вставки и обновления.

Основные критерии для индексирования

1. Поля в WHERE условиях

Первые кандидаты на индексирование — это колонки, по которым фильтруются записи:

// Запрос
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);

// Индекс
@Entity
@Table(name = "users", indexes = {
    @Index(name = "idx_email", columnList = "email", unique = true)
})
public class User {
    @Column(unique = true)
    private String email;
}

Если часто ищешь по email, обязательно индексируй это поле. unique = true автоматически создаст уникальный индекс.

2. Поля в JOIN условиях

Поля, по которым объединяются таблицы, должны быть индексированы:

// SQL
SELECT o.* FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.user_id = ?

// JPA
@Entity
public class Order {
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

// Индекс на foreign key
@Table(indexes = {
    @Index(name = "idx_order_user_id", columnList = "user_id")
})

Foreign keys обычно создают индексы автоматически, но лучше проверить.

3. Поля в ORDER BY и GROUP BY

Если часто сортируешь или группируешь по полю:

// Запрос
@Query("SELECT u FROM User u ORDER BY u.createdAt DESC")
List<User> findAllOrderByCreatedAt();

// Индекс для сортировки
@Table(indexes = {
    @Index(name = "idx_created_at", columnList = "created_at DESC")
})
public class User {
    private LocalDateTime createdAt;
}

Особенно полезны индексы в DESC порядке для выборки свежих записей.

4. Составные (комбинированные) индексы

Для сложных запросов с несколькими условиями используй составные индексы:

// SQL запрос
SELECT * FROM orders 
WHERE user_id = ? AND status = ? AND created_at > ?

// Индекс
@Table(indexes = {
    @Index(name = "idx_user_status_date", 
            columnList = "user_id, status, created_at")
})
public class Order {
    @ManyToOne
    private User user;
    private String status;
    private LocalDateTime createdAt;
}

Правило порядка полей в составном индексе (ESR rule):

  • Equality (=) — поля с точным совпадением
  • Sort (ORDER BY) — поля для сортировки
  • Range (>, <, BETWEEN) — поля с диапазоном

5. Поля в SELECT (covering index)

Включение дополнительных колонок в индекс может избежать обращения к основной таблице:

// SQL
SELECT name, email FROM users WHERE email = ?

// Covering index (включает все нужные колонки)
@Table(indexes = {
    @Index(name = "idx_email_covering", 
            columnList = "email, name")
})
public class User {
    private String email;
    private String name;
}

Пример комплексной оптимизации

@Entity
@Table(name = "orders", indexes = {
    // Основной поиск по пользователю и статусу
    @Index(name = "idx_user_status", columnList = "user_id, status"),
    
    // Поиск по дате создания
    @Index(name = "idx_created_at", columnList = "created_at DESC"),
    
    // Уникальный индекс на номер заказа
    @Index(name = "idx_order_number", columnList = "order_number", unique = true),
    
    // Поиск по статусу и дате
    @Index(name = "idx_status_date", columnList = "status, created_at DESC")
})
public class Order {
    @Id
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
    
    private String status;  // PENDING, COMPLETED, CANCELLED
    
    private LocalDateTime createdAt;
    
    private String orderNumber;
}

Чего избегать

Переиндексирование:

  • Индексы замедляют INSERT, UPDATE, DELETE операции
  • Каждый индекс требует памяти
  • Оптимально 3-5 индексов на таблицу

Неправильные индексы:

  • Индексы на низкоселективные колонки (много одинаковых значений)
  • Индексы на колонки, которые редко используются в запросах
  • Дублирующиеся индексы

Анализ и мониторинг

-- PostgreSQL: посмотреть неиспользуемые индексы
SELECT * FROM pg_stat_user_indexes 
WHERE idx_scan = 0;

-- MySQL: посмотреть статистику индексов
SELECT * FROM performance_schema.table_io_waits_summary_by_index_usage;

Заключение

Индексируй поля, которые участвуют в:

  • WHERE условиях
  • JOIN условиях
  • ORDER BY / GROUP BY
  • Уникальные и foreign key поля

Используй составные индексы для сложных запросов, но не переусложняй — лучше иметь 5 хороших индексов, чем 20 плохих.

Какие поля будешь индексировать для оптимизации запроса | PrepBro