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

dba.stackexchange https://dba.stackexchange.com/questions/197

  •  16-10-2019
  •  | 
  •  

Вопрос

Я уже немного знаю ответ на этот вопрос, но я всегда чувствую, что есть больше, что мне нужно поднять на эту тему.

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

Представьте себе стол, как так:

id int pk/uid
name varchar(50)
customerId int (foreign key)
dateCreated datetime

Я мог бы увидеть один индекс, включая name, customerId а также dateCreated поля.

Но, насколько я понимаю, такой индекс не будет использоваться в запросе, например:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

Для такого запроса мне кажется, что лучшей идеей будет индекс, включая customerId а также dateCreated поля, с customerId Поле является «первым». Это создаст индекс, который будет организованными данными таким образом, чтобы этот запрос мог бы быстро найти то, что ему нужно - в том порядке, в котором он нуждается.

Еще одна вещь, которую я вижу, возможно, так же часто, как первая, - это отдельные индексы на каждом поле; Итак, по одному на name, customerId а также dateCreated поля.

В отличие от первого примера, этот тип расположения иногда кажется мне, по крайней мере, является частично полезным; План выполнения запроса может показать, что, по крайней мере, он использует индекс на customerId Чтобы выбрать записи, но он не использует индекс с dateCreated поле для их сортировки.


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

Но я полагаю, что то, что я прошу, является общей «отправной точкой» для индексов, имеет ли идея иметь конкретные индексы для конкретных, часто выписываемых запросов и полей в том, где или порядок по предладкам?

Это было полезно?

Решение

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

Планировщик запросов рассмотрит использование индекса, если:

  • Все поля, содержащиеся в нем, упоминаются в запросе
  • Некоторые из полей, начиная с самого начала, упоминаются

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

Итак, для вашего примера:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

это рассмотрело бы индексы, такие как:

[customerId]
[customerId], [dateCreated]
[customerId], [dateCreated], [name]

но нет:

[name], [customerId], [dateCreated]

Если он нашел оба [customerId] а также [customerId], [dateCreated], [name] Его решение предпочесть одно над другим будет зависеть от статистики индекса, которые зависят от оценки баланса данных в полях. Если [customerId], [dateCreated] были определены, это должно предпочесть это над двумя другими, если вы не даете определенный индекс намека на обратное.

Нередко можно увидеть один индекс, определенный для каждого поля в моем опыте, хотя это редко оптимально, поскольку дополнительное управление, необходимое для обновления индексов на вставке/обновлении, и дополнительное пространство, необходимое для их хранения, тратят впустую, когда половина от Их никогда не используются - но если ваш БД не увидит нагрузки с тяжелыми записями, производительность не будет плохо вонять даже с избыточными индексами.

Конкретные индексы для частых запросов, которые в противном случае были бы медленными из -за таблицы или индекса, обычно являются хорошей идеей, хотя не переусердствуйте, поскольку вы можете обмениваться одной проблемой производительности на другую. Если вы определите [customerId], [dateCreated] Например, в качестве индекса помните, что планировщик запросов сможет использовать это для запросов, которые будут использовать индекс просто [customerId] если представить. Используя только [customerId] Было бы немного более эффективным, чем использование индекса соединения, это может быть смягчено, заканчивая тем, что имея два индекса, конкурирующих за пространство в ОЗУ вместо одного (хотя, если весь ваш нормальный рабочий набор легко вписывается в оперативную память, эта дополнительная конкуренция памяти может не быть проблемой) Анкет

Другие советы

Чтобы ответить на ваш первоначальный вопрос, да, индексы должны быть разработаны вокруг Запросы, не только стол. Анкет Порядок полей в индексе жизненно важен. Проектирование одного индекса, чтобы быть оптимальным для нескольких запросов, сложнее, и вам придется делать компромиссы.

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

Моя стратегия разработки индексов - индекс:

  • Поля, используемые в том, где (в порядке селективности)
  • Поля, используемые в порядке
  • Включите другие поля (при необходимости), чтобы сделать индекс покрытия

Итак, для вашего примера:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

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

Этот пример почти слишком просто, хотя. Наивный индекс справедливого (CustomerID) будет работать почти так же хорошо (при условии, что у каждого клиента есть только один повтор, поэтому потребуется только один поиск закладки в таблицу). Также может быть даже полезно сделать кластер Индекс на (CustomerId, ID), в зависимости от того, какие другие запросы выходят против таблицы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top