Один индекс или два?


11

У меня есть следующий индекс, созданный для таблицы в моей базе данных:

CREATE INDEX [idx_index1]
on [table1]
(col1, col2, col3)

Сервер предлагает следующий «отсутствующий» индекс:

CREATE INDEX [idx_index2]
on [table1]
(col1, col2)
INCLUDE (col3, col4, col5, col6....)

Мне кажется логичным изменить существующее определение индекса, включив в него предложенные столбцы, а не создавать новый индекс, который необходимо поддерживать. Запрос, который выбирает col1 и col2, может использовать index1 так же эффективно, как index2. Я прав или я что-то упускаю?

Ответы:


12

И так входит в искусство настройки производительности и стратегии индексации ...

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

Я собираюсь взять вашу цитату и написать третье определение индекса:

create index [idx_index3]
on [table1] (col1, col2, col3)
include (col4, col5, col6....);

Это должно быть CREATE INDEXутверждение, которое соответствует вашему цитируемому заявлению.

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

Если у вас общая рабочая нагрузка, которая в основном состоит из запросов, подобных этому:

select col1, col2, col3
from table1
where col1 = 1
and col2 = 2
and col3 = 3;

Тогда ваш idx_index1индекс будет твердым. Совершенно узкий, это индекс, который удовлетворяет этому запросу без посторонних данных в нем (не принимая во внимание определение кластерного индекса, если оно вообще существует).

Но если у вас есть рабочая нагрузка, которая состоит из запросов в основном, как показано ниже:

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2;

Тогда idx_index2было бы разумно, так как это то, что называется индексом покрытия, предотвращающим необходимость поиска ключа в кластеризованном индексе (или поиска RID в куче). Это определение некластеризованного индекса будет охватывать только все данные, которые необходимы для запроса.

С вашей рекомендацией, это было бы хорошо для запроса, подобного следующему:

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2
and col3 = 3;

Ваша idx_index3рекомендация - это индекс покрытия, который удовлетворяет критериям поиска для вышеуказанного запроса.

Дело в том, к чему я стремлюсь, в таком изолированном вопросе, как этот, мы не можем дать на него окончательный ответ. Все зависит от общей и частой рабочей нагрузки. Конечно, вы всегда можете определить все три из этих индексов для обработки каждого типа запроса, но тогда возникает вопрос об обслуживании, которое потребуется для обновления этих индексов (подумайте: INSERTs, UPDATEs, DELETEs). Это накладные расходы на индексы.

Вам необходимо проанализировать и оценить рабочую нагрузку и определить, где преимущества будут наилучшими. Если первый примерный запрос является наиболее распространенным и выполняется десятки раз в секунду, и существует очень редкий запрос, такой как третий примерный запрос, то не имеет смысла раздувать листовые страницы индекса с помощью INCLUDEнеключевые столбцы. Все зависит от вашей рабочей нагрузки.

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


Я собираюсь переварить это на некоторое время, но это кажется хорошим ответом. Я предполагаю, что это было опечаткой, что у 'index3', который вы определили, есть col3 как столбец равенства И включенный столбец?
Пол

Да :-) Хороший улов. Я отредактировал это.
Томас Стрингер

Не говоря уже о том, что если в таблице только столбцы 1-6, довольно глупо индексировать 1 и 2 и включать 3-5.
Кеннет Фишер

1
@KennethFisher - почему это глупо? Это кажется достаточно разумным, если ваша структура базы данных и ваша рабочая нагрузка это оправдывают. Например, если у вас есть запрос, который выбирает столбцы 1-5 на основе значений столбцов 1 и 2, и, возможно, столбец 6 является столбцом nvarchar (max), с которым вы не хотите раздувать свой индекс.
Пол

1
@paulH Вероятно, это только мое мнение, но в тот момент, когда вы добавили достаточное количество столбцов для включения, в вашем индексе содержится более 90% столбцов в таблице, и вы увеличили свой индекс до такой степени, что при дополнительном чтении можно перейти к таблице. само по себе не так уж важно. Теперь, конечно, есть исключения ... если столбцы 1-5 все int, а col6 varchar (max), тогда я мог бы это сделать. Но в целом я бы посмотрел на них ОЧЕНЬ внимательно.
Кеннет Фишер

7

Вы действительно правы и обнаружили, почему администратору БД важно всегда проверять «предложения», выдвигаемые отсутствующими индексными DMV и т. Д.

Учтите, что предложения, предлагаемые отсутствующими индексными DMV, выдвигаются изолированно, а это означает, что SQL Server решил, что индекс рекомендованной структуры будет полезен для запроса, независимо от того, какие другие структуры индекса уже могут существовать.


3

Еще немного об одном из последствий ответа Томаса:

Он сказал:

Конечно, вы всегда можете определить все три из этих индексов для обработки каждого типа запроса, но тогда возникает вопрос об обслуживании, которое потребуется для обновления этих индексов (подумайте: INSERTs, UPDATEs, DELETEs). Это накладные расходы на индексы.

Итак, возникает еще один большой вопрос: как часто обновляется таблица?

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

С другой стороны, рассмотрим таблицу, которая обновляется только как часть настройки веб-сайта - таблица обновляется ОДИН РАЗ для большинства значений, а значения добавляются нечасто - там замедления обновления в значительной степени не рассматриваются. Несколько индексов могут замедлить перестроение и перестройку индексов базы данных, но, пока они достаточно быстры, БЕСПЛАТНО: если несколько индексов ускоряют чтение, сделайте это.

Средним регистром может быть таблица, которая обычно обновляется только в пакетном процессе в течение ночи. В этом случае замедления обновления из нескольких индексов не влияют на производительность в дневное время - они будут влиять только на (1) время, затрачиваемое на выполнение этого ночного пакетного обслуживания, (2) на производительность любых параллельных процессов и (3) время, необходимое для задачи обслуживания базы данных, такие как реорганизация индекса. Итак, пока процессы в этих трех областях работают достаточно быстро для вас ... создавайте индексы, которые ускоряют запросы.

НТН ...

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.