Ответ
Только один кластерный индекс на таблицу. Это фундаментальное ограничение в большинстве реляционных СУБД (SQL Server, MySQL/InnoDB, PostgreSQL).
Почему только один? Кластерный индекс определяет физический порядок хранения данных на диске. Данные в таблице сами являются «листьями» (leaf level) кластерного индекса. Поскольку строки не могут быть физически упорядочены одновременно двумя разными способами, кластерный индекс может быть только один.
Альтернатива: некластеризованные индексы. Для ускорения других запросов можно создавать множество некластеризованных индексов. Они представляют собой отдельные структуры (например, B-деревья), которые хранят ключи индекса и указатели на соответствующие строки данных (в виде ключа кластерного индекса).
Пример в T-SQL (SQL Server):
-- Создание таблицы с кластерным индексом по полю Id (чаще всего PRIMARY KEY).
CREATE TABLE dbo.Orders (
Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED, -- Единственный кластерный индекс
OrderDate DATETIME NOT NULL,
CustomerId INT NOT NULL,
TotalAmount DECIMAL(10,2) NOT NULL
);
-- Создание некластеризованных индексов для ускорения поиска по другим полям.
-- Их может быть много (в пределах технических ограничений СУБД).
CREATE NONCLUSTERED INDEX IX_Orders_CustomerId ON dbo.Orders(CustomerId);
CREATE NONCLUSTERED INDEX IX_Orders_OrderDate ON dbo.Orders(OrderDate DESC);
Практические рекомендации по выбору поля для кластерного индекса:
- PRIMARY KEY — частый и хороший кандидат, особенно если это монотонно возрастающий ключ (IDENTITY, последовательность), что минимизирует фрагментацию.
- Выбирайте столбец (или столбцы), по которым часто происходят запросы диапазонов (range scans) (например,
WHERE Date BETWEEN ...). - Избегайте выбора широких (много столбцов) или часто изменяемых (volatile) столбцов, так как это влияет на производительность всех некластеризованных индексов и может вызывать фрагментацию.
Ответ 18+ 🔞
А, ну это классика, блядь! Сидишь такой, думаешь: "А сделаю-ка я два кластерных индекса на одну таблицу, будет быстрее!" А нихуя! Это как пытаться одновременно запихнуть данные в шкаф, отсортированные и по цвету рубашек, и по размеру. Физически, ёпта, невозможно! Данные на диске — они в одном экземпляре лежат, как последняя бутылка водки на троих.
Представь: таблица — это вот эта самая куча данных, листики в дереве. Так вот, кластерный индекс — это и есть само это дерево, ствол и ветки, а данные — это листья на нём. И дерево-то оно одно, блядь! Не может одна папка в твоём компе быть одновременно и в "Документах", и в "Загрузках" в виде оригинальных байтов. Поэтому кластерный индекс — единственный и неповторимый, как первая любовь, только с техническими ограничениями.
А как же другие запросы ускорить, спросишь? Да легко! Для этого есть некластеризованные индексы. Их — овердохуища можно наделать, в разумных пределах, конечно. Это как оглавление в конце учебника или алфавитный указатель. Отдельная структура, где написано "Иванов — см. стр. 45", а сама страница 45 — это уже кластерный индекс, то есть сами данные.
Смотри на примере, чтобы вообще пиздец как понятно стало:
-- Вот создаём таблицу заказов. PRIMARY KEY чаще всего и есть наш главный кластерный мужик.
CREATE TABLE dbo.Orders (
Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED, -- Всё! Единственный кластерный! Больше нихуя!
OrderDate DATETIME NOT NULL,
CustomerId INT NOT NULL,
TotalAmount DECIMAL(10,2) NOT NULL
);
-- А это наши палочки-выручалочки — некластеризованные индексы. Хошь по клиенту, хошь по дате — нате, получайте!
CREATE NONCLUSTERED INDEX IX_Orders_CustomerId ON dbo.Orders(CustomerId);
CREATE NONCLUSTERED INDEX IX_Orders_OrderDate ON dbo.Orders(OrderDate DESC);
Теперь, главный вопрос: а на что этот единственный кластерный индекс вешать-то, чтобы не обосраться?
- Чаще всего — на PRIMARY KEY. Особенно если это IDENTITY или sequence — данные просто подписываются в конец, как в очередь, фрагментации минимум. Идеально.
- Вешай на то, по чему часто ищешь диапазоны. Ну,
WHERE дата BETWEEN '2023' AND 'сейчас'. Если данные физически в порядке дат лежат — СУБД просто кусок прочитает и всё, быстро. - Не вешай на широкие или часто меняющиеся поля. Представь: у тебя кластерный ключ — это "ФИО + Дата рождения". Каждый раз, как кто-то фамилию меняет после замужества, всю таблицу двигать надо! А все остальные индексы, которые ссылаются на этот ключ, тоже придётся обновлять. Пиздец, а не производительность. И фрагментация будет, как после хорошей пьянки.
Короче, запомни: один кластерный — священная корова. Всё остальное — некластеризованные костыли, но очень быстрые и полезные. Держи баланс, и будет тебе счастье.