JavaRush /Курсы /SQL SELF /Проблемы избыточного индексирования

Проблемы избыточного индексирования

SQL SELF
38 уровень , 2 лекция
Открыта

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

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

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

Так что, как и с каталогами в библиотеке, с индексами важно не переборщить — лучше иметь несколько нужных и эффективных, чем десятки бесполезных.

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

  • Если ваша таблица — это большой список студентов, а индексов три, каждое добавление нового студента в таблицу приведет к трем операциям обновления индексов. Не звучит как "ускорение", правда?
  • А если у вас 10 таких таблиц, каждая из которых перегружена индексами? Производительность всей базы данных улетит в бездну.

Как определить, есть ли у вас проблема с избыточным индексированием?

Первое, что стоит сделать, чтобы понять, есть ли у вас проблема, — это посмотреть на существующие индексы. В PostgreSQL это можно сделать с помощью команды:

\d имя_таблицы

Эта команда покажет вам таблицу, ее столбцы и связанные индексы. Если вы видите огромное количество индексов, связанных с одной таблицей, это уже повод задуматься.

Еще один полезный инструмент — системный представление pg_stat_user_indexes. Оно показывает, насколько активно используются индексы, что дает понять, есть ли среди них "мертвый груз":

SELECT
    relname AS table_name,
    indexrelname AS index_name,
    idx_scan AS index_scans
FROM
    pg_stat_user_indexes
WHERE
    idx_scan = 0;

Если idx_scan равен 0, это означает, что индекс ни разу не использовался в запросах. Такой индекс — явный кандидат на удаление.

Пример избыточного индексирования

Давайте представим таблицу с пользователями:

CREATE TABLE users (
    user_id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE,
    username VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW()
);

И у нас есть три индекса:

-- Индекс на email
CREATE INDEX idx_users_email ON users (email);

-- Индекс на username
CREATE INDEX idx_users_username ON users (username);

-- Индекс на created_at
CREATE INDEX idx_users_created_at ON users (created_at);

Теперь давайте посмотрим на типичные запросы, которые мы выполняем:

  1. Поиск пользователя по email.
  2. Поиск пользователя по username.
  3. Сортировка пользователей по created_at.

Кажется, что индексы полезны. Но вот загвоздка: если эти запросы редки (скажем, раз в неделю), создание индексов не оправдано. Более того, если части этих индексов никогда не используются, они просто создают нагрузку на операции вставки и обновления данных.

Для иллюстрации: допустим, у нас есть следующие данные в таблице users:

user_id email username created_at
1 alex.lin@mail.com alexlin 2024-06-15 10:23:00
2 anna.min@mail.com annamin 2024-06-16 12:47:00
3 otto.song@mail.com ottosong 2024-06-17 08:30:00
4 maria.chi@mail.com mariachi 2024-06-18 14:10:00

Если запросы по username практически не выполняются, индекс idx_users_username ни разу не используется (idx_scan = 0) и может быть удалён для оптимизации.

То есть индекс — это отличный инструмент, но его нужно применять разумно. Лучше чтобы у нас было несколько нужных и хорошо используемых индексов, чем много лишних.

Как избежать избыточного индексирования

  1. Анализ используемых индексов. Как мы уже упоминали, проверьте статистику использования индексов с помощью pg_stat_user_indexes. Если индекс почти не используется, вероятно, его можно удалить:
DROP INDEX IF EXISTS имя_индекса;
  1. Создавайте индексы только для часто используемых запросов. Прежде чем добавлять индекс, задайте себе вопросы:
  • Часто ли этот столбец участвует в WHERE, ORDER BY, GROUP BY?
  • Большой ли объем данных в таблице?
  • Действительно ли запрос выполняется слишком медленно без индекса?

Если ответ "нет" хотя бы на один из этих вопросов, создание индекса может быть лишним.

  1. Используйте составные индексы. Если вы часто используете несколько столбцов в одном запросе, вместо создания отдельных индексов на каждый столбец создайте составной индекс:
CREATE INDEX idx_users_email_username ON users (email, username);

Это ускорит запросы, которые фильтруются по email и username одновременно.

  1. Регулярно пересматривайте существующие индексы. С ростом базы данных ваши запросы могут измениться. То, что было полезным год назад, может стать ненужным сегодня. Периодически проверяйте ваши индексы и удаляйте те, которые больше не используются.

Минимизация индексов на примере

Давайте вернемся к нашей таблице users. Вместо трех отдельных индексов мы можем оптимизировать их так:

  • Убрать отдельный индекс на created_at, если сортировка по этому столбцу случается редко.
  • Вместо двух отдельных индексов на email и username создать составной индекс:
CREATE INDEX idx_users_email_username ON users (email, username);

Итоги: в чем секрет баланса?

Как и во многих аспектах программирования, здесь работает принцип минимализма: "Чем меньше, тем лучше". Не нужно индексировать каждый столбец только потому, что вы можете. Подумайте, зачем вам нужен индекс и насколько он улучшит производительность запросов. Будьте прагматичны и помните, что хороший разработчик — не тот, кто добавляет индексы налево и направо, а тот, кто понимает их влияние и использует их эффективно.

Теперь, взяв этот инструмент в свои руки, вы можете предотвратить катастрофу избыточного индексирования и сделать вашу базу данных быстрой, как гепард, а не медленной, как черепаха с багажом ненужных индексов.

2
Задача
SQL SELF, 38 уровень, 2 лекция
Недоступна
Определение неиспользуемых индексов
Определение неиспользуемых индексов
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ