Каков лимит на количество некластеризованных индексов в таблице SQL Server и каковы практические ограничения?

Ответ

Технический лимит SQL Server (начиная с версии 2016): В одной таблице можно создать до 999 некластеризованных индексов.

Пример создания некластеризованного индекса:

-- Создание некластеризованного индекса по одному столбцу
CREATE NONCLUSTERED INDEX IX_Products_Name 
ON dbo.Products (ProductName);

-- Создание составного некластеризованного индекса
CREATE NONCLUSTERED INDEX IX_Orders_Date_Customer 
ON dbo.Orders (OrderDate DESC, CustomerID);

Практические ограничения и последствия:

  • Производительность записи (INSERT, UPDATE, DELETE): Каждый индекс — это отдельная структура данных (B-дерево), которую СУБД должна поддерживать в актуальном состоянии. Большое количество индексов значительно замедляет операции модификации данных.
  • Использование дискового пространства: Некластеризованные индексы хранят копию ключевых столбцов и указатель на строку данных (ключ кластеризованного индекса или RID).
  • Планирование запросов: Оптимизатору приходится анализировать больше вариантов выполнения, что может увеличивать время компиляции запроса.

Рекомендация: Не приближаться к техническому лимиту. Создавайте индексы адресно, основываясь на анализе реальных рабочих нагрузок (sys.dm_db_index_usage_stats). Для большинства таблиц оптимально иметь 5-15 осмысленных индексов.

Ответ 18+ 🔞

А, слушай, вот это тема! Ты знаешь, что в SQL Server, начиная с 2016-го, можно на одну таблицу навесить до 999 некластеризованных индексов? Представляешь, девятисот девяносто девяти, Карл! Овердохуища!

Но это, блядь, чисто технический лимит, как предел прочности на разрыв. Это не значит, что нужно туда стремиться, это значит, что если ты до него дотянешься, то тебе уже давно пора в психушку, а базу — под медный таз.

Вот смотри, как их создают, эти индексы-муму:

-- Простой индекс на одно поле, например, на название товара
CREATE NONCLUSTERED INDEX IX_Products_Name 
ON dbo.Products (ProductName);

-- А вот составной, чтоб два раза не вставать: по дате заказа (сверху свежие) и клиенту
CREATE NONCLUSTERIZED INDEX IX_Orders_Date_Customer 
ON dbo.Orders (OrderDate DESC, CustomerID);

Код-то простой, да? А теперь подумай головой, э бошка думай! Что будет, если ты начнёшь плодить их, как сука, кроликов?

  1. Запись (INSERT/UPDATE/DELETE) превратится в ад. Каждый новый индекс — это отдельное деревце (B-дерево), которое система обязана латать при каждой твоей правке данных. Добавил ты сто индексов — и каждая вставка превращается в сто маленьких дополнительных записей. База просто ляжет и заплачет, как Герасим над Муму, когда уже поздно.

  2. Место на диске сожрёт. Каждый такой индекс хранит копии тех столбцов, по которым построен, плюс ссылку на сами данные. Хуй с горы, если таблица большая — индексы могут спокойно съесть места больше, чем сами данные.

  3. Оптимизатор запросов с ума сойдёт. Ему же надо проанализировать ВСЕ возможные пути через эти ебаные индексы, чтобы выбрать самый быстрый. А когда их сотни, он может так задуматься, что твой запрос скомпилируется дольше, чем выполнится влоб.

Так что моя главная рекомендация, чтоб тебя чих-пых в сраку: забей на лимит в 999. Это мартышлюшка для распиздяев. Для нормальной, живой таблицы золотая середина — это где-то от 5 до 15 толковых, выверенных индексов. Не больше!

А чтобы понять, какие именно нужны, не гадай на кофейной гуще. Иди и смотри, как система реально работает: sys.dm_db_index_usage_stats тебе в помощь. Создавай индексы адресно, под конкретные тяжёлые запросы, а не просто потому что можешь. А то будет как в той сказке — накрылся медным тазом, а виновата собака.