В каких случаях использование индексов в БД может быть неэффективным или вредным?

Ответ

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

  1. Низкая селективность колонки

    • Индекс наиболее полезен, когда он помогает выбрать небольшую долю записей. Если по условию WHERE находится большая часть таблицы (например, status = 'active', где 90% записей активны), СУБД может решить, что полное сканирование таблицы (Full Table Scan) будет быстрее, чем чтение индекса и последующий доступ к данным.
  2. Накладные расходы на запись (INSERT, UPDATE, DELETE)

    • При каждой операции изменения данных СУБД должна обновить не только саму таблицу, но и все связанные с ней индексы. Это замедляет операции записи, особенно в таблицах с большим количеством индексов.
  3. Неправильное использование составных (многоколоночных) индексов

    • Порядок колонок в составном индексе критически важен. Индекс на (col_a, col_b) будет эффективно использоваться для запросов с WHERE col_a = ? или WHERE col_a = ? AND col_b = ?, но будет бесполезен для запроса с WHERE col_b = ?.
  4. Использование функций над индексированными колонками

    • Применение функций к колонке в условии WHERE (например, WHERE LOWER(name) = 'test') почти всегда делает использование индекса по этой колонке невозможным.
  5. Большой размер индексов

    • Индексы занимают место на диске и в оперативной памяти. Если индексы слишком велики и не помещаются в RAM, их эффективность падает из-за постоянных дисковых операций.

Пример неэффективного использования:

-- Индекс на колонку с низкой селективностью (например, пол пользователя)
CREATE INDEX idx_gender ON users(gender);

-- Этот запрос, скорее всего, проигнорирует индекс и выполнит полное сканирование таблицы,
-- так как он выбирает примерно 50% всех строк.
SELECT * FROM users WHERE gender = 'female';

Ответ 18+ 🔞

А, слушай, про индексы в базах данных. Ну, вроде как волшебная таблетка, да? Сделал индекс — и всё летает. Ан нет, ёпта! Тут такие подводные ебучки есть, что мама не горюй. Сейчас разжую.

Вот представь: индекс — это как алфавитный указатель в конце толстой книжки. Ищет быстро, да. Но если ты ищешь не слово, а, блядь, все слова, где есть буква «А» — так это ж почти вся книжка! Зачем тогда по указателю прыгать, если проще всю херовину с начала до конца пролистать? Так и база думает. Если ты через WHERE выгребаешь овердохуища записей (типа status = 'active', а активных там 90%), то она махнёт рукой и пойдёт читать всю таблицу подряд. Индекс в этом случае — как пятое колесо у телеги, только место жрёт.

А теперь про главную боль — запись. Каждый раз, когда ты вставляешь новую запись (INSERT), обновляешь (UPDATE) или, не дай бог, удаляешь (DELETE), база должна не только саму таблицу потрогать, но и ВСЕ индексы к ней прикрученные обновить. Представь, у тебя таблица и на ней, как гирлянды на ёлке, десять индексов висит. Каждая запись — это десять лишних операций! Запись начинает ползти, как черепаха в сиропе. Вот и думай, нужны ли тебе все эти индексы, или ты просто коллекционируешь их, блядь.

Составные индексы — это вообще отдельный цирк. Порядок колонок — всё! Создал индекс на (col_a, col_b). Ищешь по col_a — красота, летит. Ищешь по col_a и col_b вместе — вообще песня. А попробуй найти только по col_b... И что? А нихуя! Индекс-то твой начинается с col_a, а без неё он слепой, как крот. Стоит там, тупит, и база опять идёт читать всю таблицу. Мартышлюшка!

Ещё одна классика жанра — умники, которые любят в запросе функции применять. На колонке name индекс есть, а в запросе пишут WHERE LOWER(name) = 'test'. Ну и что этот индекс теперь стоит, а? Он же построен на обычных значениях name, а не на их нижнем регистре! База смотрит на эту хуйню, вздыхает и опять идёт сканировать всё подряд, вычисляя LOWER для каждой строки. Пиздец, а не оптимизация.

Ну и размер, куда ж без него. Индексы — они же не из воздуха берутся. Место на диске жрут, а главное — в оперативке сидеть любят. Если индекс такой здоровый, что в память не влезает, то каждый раз, чтобы по нему что-то найти, придётся кусками с диска таскать. Скорость сразу накрывается медным тазом. Получается, хотел как лучше, а вышло как всегда.

Вот тебе наглядный пиздец:

-- Допустим, надумали мы проиндексировать пол пользователей. Гениально!
CREATE INDEX idx_gender ON users(gender);

-- А теперь выбираем всех женщин. Их, допустим, 50% от всех.
SELECT * FROM users WHERE gender = 'female';

Что сделает умная база? Она посмотрит на этот индекс idx_gender, прикинет, что женщин — половина всей таблицы, и скажет: «Да похуй! Читать индекс, а потом по нему ещё и в таблицу прыгать — это дольше, чем просто всю таблицу разом прочитать». И проигнорирует твой индекс нахрен. Зря создавали, зря место тратили. Вот и вся магия, блядь.