Ответ
Кластерный индекс определяет физический порядок хранения строк данных в таблице. Таблица может иметь только один кластерный индекс, так как данные не могут быть физически упорядочены более чем одним способом. В SQL Server и MySQL (InnoDB) первичный ключ по умолчанию создает кластерный индекс.
Некластерный индекс — это отдельная структура, которая хранит отсортированные ключевые значения вместе с указателями на фактические строки данных (row locators). На одну таблицу можно создать множество некластерных индексов.
Ключевые различия:
| Аспект | Кластерный индекс | Некластерный индекс |
|---|---|---|
| Количество | Один на таблицу | Множество на таблицу |
| Структура | Данные таблицы физически отсортированы | Отдельная структура (B-дерево) с указателями |
| Скорость чтения | Быстрее для диапазонных запросов и поиска по первичному ключу | Быстрее для точечных запросов по индексируемым полям |
| Скорость вставки | Медленнее (требуется переупорядочивание) | Быстрее (добавляется только запись в индекс) |
| Хранение | Содержит сами данные | Содержит ключи + указатели на данные |
Примеры в SQL:
-- Создание таблицы с кластерным индексом (первичный ключ)
CREATE TABLE Orders (
OrderID INT PRIMARY KEY, -- Создает кластерный индекс
CustomerID INT,
OrderDate DATE,
Amount DECIMAL(10,2)
);
-- Создание некластерного индекса
CREATE NONCLUSTERED INDEX IX_Orders_CustomerID
ON Orders(CustomerID);
-- Составной некластерный индекс
CREATE NONCLUSTERED INDEX IX_Orders_Date_Customer
ON Orders(OrderDate DESC, CustomerID);
Практический опыт: В проектах с высокой нагрузкой на запись я тщательно проектирую кластерный индекс, чтобы минимизировать фрагментацию. Для часто запрашиваемых полей, не входящих в кластерный индекс, создаю покрывающие некластерные индексы (covering indexes), которые включают все необходимые для запроса столбцы, чтобы избежать обращений к самой таблице (key lookups).
Ответ 18+ 🔞
А, ну это про индексы, ёпта! Сидишь такой, думаешь — ну что за хуйня, почему одна таблица тормозит, как черепаха в патоках? А потом вспоминаешь, что индексы — это как карта сокровищ для базы данных, без них она слепая и тупая.
Смотри, есть два главных типа: кластерный и некластерный. Разница между ними — как между твоей старой, засаленной кроватью, где всё валяется в одном месте (кластерный), и умным шкафом с кучей полочек для каждой хуйни (некластерный).
Кластерный индекс — это царь и бог таблицы. Он один, как первичный пахан. Он не просто указывает на данные, он и есть сами данные, упорядоченные по выбранному ключу. Создаёшь PRIMARY KEY — и бац, у тебя уже есть кластерный индекс (в SQL Server и InnoDB). Данные на диске лежат именно в этом порядке. Поэтому он быстрый для поиска по этому ключу и для выборки диапазонов. Но, бля, есть подвох: если вставляешь запись не в конец, а куда-то в середину, системе приходится двигать всё остальное, как в переполненном автобусе, — это может быть долго. Один на таблицу, и точка.
Некластерный индекс — это уже отдельная, хитрая структура. Как записная книжка с оглавлением. В ней хранятся отсортированные значения выбранных полей (например, CustomerID или OrderDate) и указатели на то место в куче или кластерном индексе, где лежат полные данные строки. Таких индексов можно наделать овердохуища, под каждую частую операцию поиска. Быстро нашли по индексу, а потом — прыг! — по указателю за остальными данными.
Вот тебе ключевые различия, чтобы не путать:
| Что сравниваем | Кластерный индекс (Царь) | Некластерный индекс (Шкаф с полками) |
|---|---|---|
| Сколько можно | Один, блядь! | Много, хоть всю таблицу ими облепи |
| Что внутри | Сами строки данных, упорядоченные | Ключи + адреса-указатели на строки |
| Читает | Охуенно быстро, если по его порядку | Быстро находит ключ, но потом может быть прыжок |
| Вставляет/Обновляет | Иногда медленно, если порядок ломается | Обычно быстрее, просто добавил запись в свой список |
| Занимает место | Это и есть данные, места не занимает отдельно | Занимает, иногда прилично, это же отдельная структура |
На практике это выглядит так:
-- Создаём таблицу. PRIMARY KEY сделает кластерный индекс по OrderID.
-- Данные на диске будут лежать в порядке возрастания OrderID.
CREATE TABLE Orders (
OrderID INT PRIMARY KEY, -- Вот он, пахан кластерный
CustomerID INT,
OrderDate DATE,
Amount DECIMAL(10,2)
);
-- А это уже некластерный индекс. Отдельная структура для быстрого поиска по CustomerID.
CREATE NONCLUSTERED INDEX IX_Orders_CustomerID
ON Orders(CustomerID);
-- Составной некластерный индекс. Сначала по дате (сортировка обратная), потом по клиенту.
-- Удобно для отчётов "покажи заказы за вчера".
CREATE NONCLUSTERED INDEX IX_Orders_Date_Customer
ON Orders(OrderDate DESC, CustomerID);
А теперь жизненный лайфхак, чувак. Когда нагрузка дикая, и запросы летят каждую секунду, просто накидать индексов — мало. Надо думать.
- Кластерный индекс выбирай с умом. Чаще всего это монотонно растущий PK (типа IDENTITY). Чтобы новые записи просто приклеивались в конец, а не вызывали пиздец с фрагментацией.
- Некластерные индексы делай "покрывающими" (covering). Это когда в индекс включаешь не только поля для поиска, но и те, которые нужны в SELECT. Тогда запросу вообще не надо лезть в саму таблицу — всё есть в индексе. Это как если бы в оглавлении книги была не только страница, но и сам абзац. Скорость взлетает до небес.
В общем, индексы — это не магия, а инструмент. Используй с умом, а не как мартышлюшка, которая на кнопки тыкает. И тогда твоя база не будет бздеть на каждый запрос.