Что такое некластеризованный индекс в реляционных базах данных?

Ответ

Некластеризованный индекс — это отдельная от данных структура (например, B-дерево), которая хранит отсортированные ключи индекса и указатели (адреса) на соответствующие строки в таблице. Он не изменяет физический порядок данных на диске.

Аналогия: Оглавление в книге. Страницы (данные) лежат в своем порядке, а оглавление (индекс) — отдельно и позволяет быстро найти нужную страницу.

Создание индекса (SQL):

-- Создание некластеризованного индекса по одному столбцу
CREATE INDEX idx_lastname ON employees(last_name);

-- Создание составного некластеризованного индекса
CREATE INDEX idx_name_department ON employees(last_name, department_id);

-- Создание уникального некластеризованного индекса
CREATE UNIQUE INDEX idx_email ON users(email);

Как он работает?

  1. При поиске по индексированному столбцу СУБД сначала ищет значение в индексе (быстро, т.к. данные отсортированы).
  2. Находит указатель на физическое расположение строки (например, RID — Row Identifier).
  3. По указателю извлекает полную строку из таблицы (операция bookmark lookup или key lookup).

Преимущества:

  • Ускорение поиска (WHERE) и сортировки (ORDER BY) по индексированным столбцам.
  • Можно создать множество индексов на одну таблицу (в отличие от одного кластеризованного).
  • Не перестраивает таблицу при создании или удалении.

Недостатки и затраты:

  • Дополнительное дисковое пространство: Индекс хранит копии ключевых значений и указатели.
  • Накладные расходы на запись: При INSERT, UPDATE, DELETE в индексированных столбцах СУБД должна обновлять и таблицу, и все affected индексы.
  • Bookmark lookup: Если запрос требует данных, не входящих в индекс, происходит дополнительное обращение к таблице, что может быть дорого.

Когда использовать? Для столбцов, часто используемых в условиях WHERE, JOIN, ORDER BY. Избегайте индексов на часто изменяемые столбцы или маленькие таблицы.

Ответ 18+ 🔞

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

Представь себе, блядь, толстенную книгу — «Войну и мир», например. Страницы там идут по порядку, как напечатали, так и лежат. Это наша таблица с данными, физически на диске. Теперь, если тебе надо найти, где там про какого-нибудь Курагина, ты что будешь делать? Листать всю книгу, страницу за страницей? Это пиздец как долго, ёпта! Вот именно так и работает запрос без индекса — полное сканирование таблицы, или, как умные дяди говорят, TABLE SCAN. Хуёво.

А теперь смотри, в начале книги есть оглавление. Там написано: «Курагин — страница 123». Ты сразу перепрыгиваешь на нужную страницу. Это и есть некластеризованный индекс, сука! Сама книга (данные) не перепечатывается, страницы не перемешиваются. Просто отдельно существует эта папочка-указатель, где всё отсортировано по алфавиту (или по числам — это уже B-дерево, но суть та же).

Как это в коде выглядит, блядь:

-- Делаем такой вот указатель по фамилии сотрудников
CREATE INDEX idx_lastname ON employees(last_name);

-- Или вот комбинированный указатель, чтоб и по фамилии и отделу искать
CREATE INDEX idx_name_department ON employees(last_name, department_id);

-- А это чтоб почты не повторялись, уникальный такой сторож
CREATE UNIQUE INDEX idx_email ON users(email);

А теперь, как эта мартышлюшка работает изнутри, на пальцах:

  1. Ты пишешь запрос: SELECT * FROM employees WHERE last_name = 'Иванов'.
  2. База данных, такая хитрая жопа, не лезет сразу в кучу данных. Она говорит: «Ага, у меня же есть этот idx_lastname!». Полезла в этот отсортированный список, быстро нашла «Иванов» (потому что бинарный поиск, ебать его в сраку, это быстро).
  3. Рядом с «Иванов» в индексе лежит адрес, где эта строка валяется в основной куче страниц (этот адрес называется RID — Row ID). Типа «Иванов — полка 3, коробка 5, файл 12».
  4. База хватает этот адрес и идёт по нему, чтобы вытащить уже всю строку — зарплату, дату найма и прочую хуйню. Эта операция называется bookmark lookup или key lookup.

Плюсы этой затеи, понятное дело, есть:

  • Искать (WHERE) и сортировать (ORDER BY) становится в разы быстрее. Не надо всю таблицу перелопачивать.
  • Таких указателей-индексов можно наделать овердохуища на одну таблицу. Кластеризованный индекс (который переставляет сами данные) может быть только один, а этих — хоть двадцать.
  • Создал индекс — и данные на диске даже не пошевелились. Не как с кластеризованным, где всё приходится физически перекладывать.

Но и минусы, блядь, жирные, куда без них:

  • Место жрёт. Индекс — это же отдельная структура, копия твоих ключевых полей плюс адреса. Чем больше индексов — тем больше места на диске сожрали.
  • Запись замедляет. Представь: ты добавляешь нового сотрудника в таблицу. Ладно, добавил. А теперь надо во ВСЕ индексы, где есть его фамилия, отдел или почта, тоже добавить запись, да ещё и в отсортированном порядке вставить. При UPDATE или DELETE — та же история, всё надо синхронизировать. Каждая операция вставки превращается в «впендюрить в таблицу + взъебнуть во все индексы».
  • Проклятый bookmark lookup. Вот самый частый косяк. Допустим, у тебя индекс только на last_name. Ты ищешь по фамилии — ок, индекс сработал, адрес нашел. Но если тебе нужны ещё и другие поля (salary, phone), которых в индексе нет, то системе приходится по найденному адресу идти в основную таблицу и дёргать оттуда всю строку. Если таких строк много (ты ищешь всех Ивановых в большой компании), то это превращается в тысячи лишних обращений к данным. И вместо быстрого поиска получается пиздец.

Так когда же эту штуку использовать, а? Используй для столбцов, по которым ты реально часто ищешь (WHERE), соединяешь таблицы (JOIN) или сортируешь (ORDER BY). Как на почту, логин, фамилию, айдишник категории.

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

Вот так вот, ёпта. Индекс — это как костыль: если нога сломана (запрос тормозной) — то без него никуда. А если здоровый — так он только мешать будет, под мышками натирать.