Использовал ли вы индексы в базах данных и как их оптимизировали?

«Использовал ли вы индексы в базах данных и как их оптимизировали?» — вопрос из категории Базы данных, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, активно работал с индексами как в SQL (PostgreSQL), так и в NoSQL (MongoDB) базах данных в контексте Node.js приложений.

Для PostgreSQL с Node.js:

// Создание индексов через миграции Knex
exports.up = function(knex) {
  return knex.schema.table('users', function(table) {
    // Простой индекс
    table.index('email');

    // Составной индекс для частых запросов
    table.index(['status', 'created_at']);

    // Уникальный индекс
    table.unique('username');

    // Частичный индекс (только для активных пользователей)
    knex.raw('CREATE INDEX idx_users_active ON users(id) WHERE status = 'active'');
  });
};

Для MongoDB с Mongoose:

// Определение индексов в схеме
const userSchema = new mongoose.Schema({
  email: { type: String, required: true },
  companyId: { type: mongoose.Schema.Types.ObjectId },
  createdAt: { type: Date, default: Date.now }
});

// Простой индекс
userSchema.index({ email: 1 });

// Составной индекс
userSchema.index({ companyId: 1, createdAt: -1 });

// TTL индекс для автоматического удаления старых записей
userSchema.index({ createdAt: 1 }, { expireAfterSeconds: 2592000 }); // 30 дней

Как я анализировал и оптимизировал индексы:

  1. Использовал EXPLAIN в PostgreSQL:

    EXPLAIN ANALYZE 
    SELECT * FROM orders 
    WHERE user_id = 123 AND status = 'completed' 
    ORDER BY created_at DESC;
  2. Мониторинг через pg_stat_user_indexes: Отслеживал, какие индексы реально используются

  3. Практические правила, которые применял:

    • Индексировал поля в WHERE, JOIN, ORDER BY — особенно в часто выполняемых запросах
    • Использовал составные индексы для запросов с несколькими условиями, учитывая порядок полей
    • Избегал избыточных индексов — удалял дублирующиеся или редко используемые
    • Для текстового поиска использовал GIN/GIST индексы в PostgreSQL или text index в MongoDB

Пример проблемы и решения: На одном проекте запрос поиска заказов по диапазону дат выполнялся 2+ секунды. Добавил индекс (user_id, created_at) и время уменьшилось до 50ms, так как PostgreSQL смог использовать индекс только для чтения (index-only scan).