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

У меня есть таблица в базе данных SQL Server, с которой я хочу как можно быстрее искать и извлекать данные. Мне не важно, сколько времени требуется для вставки в таблицу, меня интересует только скорость, с которой я могу получить данные.

Проблема заключается в доступе к таблице с 20 или более разными типами запросов. Это делает утомительную задачу для добавления индекса, специально разработанного для каждого запроса. Я рассматриваю вместо этого просто добавление индекса, который включает ВСЕ столбцы таблицы. Это не то, что вы обычно делаете в "хорошем" дизайне базы данных, поэтому я предполагаю, что есть веская причина, почему я не должен этого делать.

Может ли кто-нибудь сказать мне, почему я не должен этого делать?

ОБНОВЛЕНИЕ: Я забыл упомянуть, я также не забочусь о размере моей базы данных. Это нормально, что это означает, что размер моей базы данных будет больше, чем нужно

7 ответов

Прежде всего, индекс в SQL Server может содержать не более 900 байт в своей записи индекса. Это само по себе делает невозможным наличие индекса со всеми столбцами.

Больше всего: такой индекс не имеет никакого смысла. Чего вы пытаетесь достичь?

Рассмотрим это: если у вас есть индекс на (LastName, FirstName, Street, City), этот индекс будет не использоваться для ускорения запросов на

  • FirstName
  • City
  • Street

Этот индекс будет полезен для поиска по

  • (LastName), или
  • (LastName, FirstName), или
  • (LastName, FirstName, Street), или
  • (LastName, FirstName, Street, City)

но на самом деле ничего другого - конечно, если вы ищете только Street или просто City!

Порядок столбцов в вашем индексе имеет большое значение, и оптимизатор запросов не может просто использовать какой-либо столбец где-то посередине индекса для поиска.

Рассмотрите свою телефонную книгу: она, вероятно, может быть отправлена ​​по LastName, FirstName, может быть, на Street. Так что эта индексация поможет вам найти все "Джо" в вашем городе? Все люди, живущие на "Мейн-стрит"? Нет - вы можете сначала искать LastName - тогда вы получите более конкретную информацию внутри этого набора данных. Просто наличие индекса по всему не ускоряет поиск всех столбцов вообще.

Если вы хотите иметь возможность искать по Street - вам нужно добавить отдельный индекс на (Street) (и, возможно, другой столбец или два, которые имеют смысл).

Если вы хотите иметь возможность искать по Occupation или что-то еще - для этого вам нужен другой конкретный индекс.

Просто потому, что ваш столбец существует в индексе, не означает, что ускорит все поиски этого столбца!

Главное правило: использовать как можно меньше индексов - слишком много индексов может быть еще хуже для системы, чем вообще не иметь индексов... стройте свою систему, контролируйте ее производительность и находите те запросы, которые стоят большинство - затем оптимизируйте их, например путем добавления индексов.

Не просто слепо индексировать каждый столбец только потому, что вы можете - это гарантия застойной производительности системы. Любой индекс также требует обслуживания и поддержки, поэтому чем больше индексов у вас есть, тем больше операций INSERT, UPDATE и DELETE страдают (замедляются), так как все эти индексы необходимо обновить.


У вас есть фундаментальное непонимание того, как работают индексы.

Прочтите это объяснение " как работают многоколонные индексы.

Следующий вопрос, который у вас может возникнуть, - это почему бы не создать один индекс за столбец - но это тоже тупик, если вы попытаетесь достичь верхний выбор производительности.

Вы можете почувствовать, что это утомительная задача, но я бы сказал, что это требуемая задача для тщательного индексации. Неверное индексирование удаляется, как в в этом примере.

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


Если это операция типа хранилища данных, где запросы очень оптимизированы для запросов READ, и если у вас есть 20 способов анализа данных, например

Предложение WHERE включает в себя..

Q1: status, type, customer
 Q2: price, customer, band
 Q3: sale_month, band, type, status
 Q4: customer
 etc

И у вас абсолютно много свободного места для записи, а затем создайте индекс для КАЖДОГО одного столбца, отдельно. Таким образом, таблица из 20 столбцов будет содержать 20 индексов, по одному для каждого отдельного столбца. Я мог бы, вероятно, сказать, чтобы игнорировать столбцы бит или столбцы с низкой мощностью, но поскольку мы зашли так далеко, зачем беспокоиться (с этим предупреждением). Они будут просто сидеть и сбрасывать время WRITE, но если вам не нужна эта часть картины, тогда мы все хорошо.

Проанализируйте свои 20 запросов, и если у вас есть горячие запросы (самые горячие), которые по-прежнему не будут выполняться быстрее, планируйте его с помощью SSMS (нажмите Ctrl-L) с одним запросом в окне запроса. Он расскажет вам, какой индекс может помочь этим запросам - просто создайте его; создайте их все, полностью помня, что это снова добавляет стоимость записи, размер файла резервной копии, время обслуживания db и т.д.


... если вы добавите индекс, содержащий все столбцы, и запрос действительно сможет использовать этот индекс, он будет сканировать его в порядке первичного ключа. Это означает, что вы попадаете почти на каждую запись. Среднее время поиска будет O (n/2).. то же, что и для фактической базы данных.

Вам нужно прочитать фрагмент bit об индексах.

Это может помочь, если вы считаете индекс в таблице немного похожим на словарь в С#.

var nameIndex = new Dictionary<string, list<int="">>();
</string,>

Это означает, что столбец имен проиндексирован и вернет список первичных ключей.

var nameOccupationIndex = new Dictionary<string, list<dictionary<string,="" list<int="">>>>();
</string,>

Это означает, что столбцы имен + столбцы заполнения индексируются. Теперь представьте, что индекс содержал 10 разных столбцов, вложенных до сих пор в глубину, он содержит каждую строку в вашей таблице.

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


Я рассматриваю вместо этого просто добавление индекса, который включает ВСЕ столбцы таблицы.

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

Это не так просто, как "добавить все, чтобы индексировать и иметь сон"


1), индекс по существу создает копию данных в этом столбце, какую-то структуру с легкостью поиска, такую ​​как двоичное дерево (я не знаю спецификаций SQL Server). 2) Вы упомянули скорость, структуры индексов медленнее добавить.


Этот индекс будет просто идентичен вашей таблице (возможно, отсортирован в другом порядке). Это не ускорит ваши запросы.

licensed under cc by-sa 3.0 with attribution.