Какие ситуации, кроме дублирования записей, могут привести к несоответствию данных в индексе и таблице базы данных?

Ответ

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

  • NULL-значения. Индексы, как правило, не включают строки, где все проиндексированные столбцы содержат NULL. Запрос, ищущий WHERE column IS NULL, может не использовать индекс.
  • Несоответствие типов данных. Сравнение без явного приведения типов (например, VARCHAR с INT) может обойти индекс.
  • Частичное использование составного индекса. Составной индекс (A, B, C) эффективен только для запросов, использующих префикс этого набора (A; A,B; A,B,C). Запрос по полю B или C без A — нет.
  • Использование функций или выражений в WHERE. Индекс строится на исходных значениях колонки. Условия вида WHERE UPPER(name) = 'ALICE' или WHERE YEAR(date_column) = 2024 обычно игнорируют индекс по name или date_column.
  • Неоптимальный порядок столбцов в составном индексе. Порядок должен соответствовать частотности и селективности запросов.

Пример с функцией:

-- Индекс по `name` НЕ будет использован
SELECT * FROM users WHERE UPPER(name) = 'ALICE';

-- Индекс по `name` БУДЕТ использован
SELECT * FROM users WHERE name = 'Alice';
-- Для первого случая можно создать функциональный индекс: CREATE INDEX idx_upper_name ON users(UPPER(name));

Ответ 18+ 🔞

А, слушай, вот ещё какие подводные ебучки бывают, когда индекс вроде есть, а запрос всё равно ползёт как черепаха по стекловате. Это ж классика, блядь! Помимо того, что данные могут разъебаться, есть ещё куча нюансов, про которые все забывают, а потом охуевают.

Смотри, вот тебе топ причин, почему твой запрос сосёт, а индекс — хуй с ним:

  • NULL-значения, ёпта. Индексы — они такие хитрожопые, обычно игнорируют строки, где во всех проиндексированных полях сидит NULL. Так что если ты ищешь WHERE column IS NULL, то готовься к полному скану таблицы, потому что индекс тебе, скорее всего, не поможет. Он просто не знает про этих невидимок.
  • Несоответствие типов данных. Ну это вообще пиздец, как часто бывает! База хранит число, а ты в запросе сравниваешь его со строкой, без всякого приведения. Типа WHERE int_column = '123'. Оптимизатор смотрит на это и думает: «Ну нахуй, тут явное приведение нужно, индекс по int_column не подходит». И пошёл таблицу драить.
  • Частичное использование составного индекса. Вот тут, блядь, многие обжигаются. Создали индекс на три поля (A, B, C). Думают, теперь всё летает. А он, сука, работает только если ты начинаешь с поля A! То есть запросы WHERE A = 1, WHERE A = 1 AND B = 2 или WHERE A = 1 AND B = 2 AND C = 3 — да, огонь. А вот если ты полез с запросом WHERE B = 2 или WHERE C = 3 — хуй тебе, а не индекс. Он как телефонная книга, отсортированная по фамилии, а потом имени. Попробуй найти всех Васюков по имени «Петя» — нихуя не выйдет, надо листать всю.
  • Использование функций или выражений в WHERE. Это, блядь, убийца номер один! Индекс — это слепок исходных данных колонки. А если ты в условии начинаешь эти данные ебашить функциями, то всё, пиши пропало. Индекс становится бесполезным, как зонтик в ураган.

Пример с функцией, чтобы совсем понятно было:

-- Индекс по `name` НЕ будет использован. Потому что в индексе лежит 'Alice', а ты ищешь UPPER('Alice').
-- Оптимизатор не дурак, он не будет для каждой строки вычислять UPPER и потом сравнивать с индексом. Он проще сделает full scan.
SELECT * FROM users WHERE UPPER(name) = 'ALICE';

-- А вот тут индекс по `name` БУДЕТ использован. Всё честно, ищем то, что есть.
SELECT * FROM users WHERE name = 'Alice';
-- Кстати, если уж очень надо искать через UPPER, можно создать специальный, функциональный индекс: CREATE INDEX idx_upper_name ON users(UPPER(name));
  • Неоптимальный порядок столбцов в составном индексе. Это уже высший пилотаж, блядь. Порядок полей — это не просто так. Ставить надо сначала самое селективное (то, что лучше всего отсеивает строки) и то, что чаще всего используется в запросах. Если поставить на первое место поле, где у всех строк значение 1, то от такого индекса толку — как от козла молока.

Вот так-то, дружок. База данных — она живая, блядь. Надо с ней аккуратно, с пониманием. А не просто тыкать CREATE INDEX на всё подряд и надеяться на чудо.