Индексирование стратегии на столе - PullRequest
4 голосов
/ 07 января 2009

У меня есть таблица SQL Server 2005 с именем EventTable, определенная следующим образом:

EventID, EventTypeCode, EventStatusCode, EventDate

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

Столбцы EventTypeCode и EventStatusCode имеют тип CHAR (3) (примеры «NEW», «SEN», «SAL») и являются внешними ключами

Общий выбор будет ...

select * from EventTable Where EventDate = @dateparam;
select * from EventTable Where EventTypeCode = @eventtype;
select * from EventTable Where EventStatusCode = @statustype;

Какую стратегию индекса вы бы использовали для обработки операторов Select выше?

Лучше ли иметь индекс покрытия (составной) по 3 столбцам? Если да, то в каком порядке должен быть составной индекс?

Или отдельный индекс для каждого из 3 столбцов?

Таблица будет расти со скоростью около 300 событий в день.


Также будет распространено выполнение запросов, таких как where EventDate between '2008-12-01' and '2008-12-31' and EventTypeCode = 'todo'

  • таблица, скорее всего, будет расти на 500-800 / записей в день, а не на 300
  • запросы, упомянутые в первоначальном вопросе, будут выполняться много раз в течение дня при обычном использовании приложения ASP.NET
  • NHibernate 'HQL' используется для выполнения таких запросов
  • первоначальная загрузка данных отсутствует, таблица теперь находится на уровне около 10K записей, потому что это новое приложение
  • ... Я более или менее просто пытаюсь избежать того, что клиенту придется звонить нам через пару лет, чтобы жаловаться на то, что приложение становится «медленным», так как за этим столом будет очень много

Ответы [ 4 ]

6 голосов
/ 07 января 2009

Стратегия 1, укажите индексы, которые можно использовать для фильтрации. Таблица поиска будет извлекать оставшиеся данные. Это почти вдвое увеличивает использование пространства, и стоимость ввода-вывода при записи увеличивается в четыре раза.

on EventTable(EventDate)
on EventTable(EventTypeCode)
on EventTable(EventStatusCode)

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

on EventTable(EventDate, EventId,
              EventTypeCode, EventStatusCode)
on EventTable(EventTypeCode, EventId,
              EventDate, EventStatusCode)
on EventTable(EventStatusCode, EventId,
              EventDate, EventTypeCode)

Причина, по которой порядок столбцов имеет значение в индексе покрытия (в общем), заключается в том, что данные упорядочены по каждому столбцу по очереди. То есть: столбцы 2 тай-брейков столбец 1. столбец 3 тай-брейков столбцы 1 и 2.

Поскольку у вас нет запросов, которые фильтруют по нескольким столбцам, в вашем случае не имеет значения (в вашем случае) порядок столбцов после первого столбца.

Если у вас был запрос, например

where EventDate = @EventDate
  and EventTypeCode = @EventTypeCode

Тогда этот индекс покрытия будет полезен. EventDate, вероятно, более избирателен, чем EventTypeCode, поэтому он идет первым.

on EventTable(EventDate, EventTypeCode,
              EventId, EventStatusCode)

Редактировать дальше: Если у вас есть запрос, такой как

where EventDate between '2008-12-01' and '2008-12-31'
  and EventTypeCode = 'todo'

Тогда этот индекс будет работать лучше:

on EventTable(EventTypeCode, EventDate,
              EventId, EventStatusCode)

Это объединит все события 'todo', упорядоченные по их EventDate в качестве тай-брейка. SQL Server просто должен найти первый элемент и прочитать его, пока не найдет элемент, который не соответствует критериям, и не остановится.

Если бы EventDate был первым в индексе, то данные были бы упорядочены по дате, а затем в каждой дате были бы сгруппированы вместе события 'todo'. SQL Server найдет первое задание 12-01, прочитает, пока не найдет элемент, который не соответствует критериям ... затем найдет первое задание 12-02, прочитает, пока не выйдет из задания ... затем найдет. .. в течение 31 дня.

Вы хотите выбрать индекс, который помещает элементы, которые вы хотите, смежные друг с другом.


При 300 записях в день ваша таблица получит до 5 миллионов записей за 50 лет. Это не так уж и много. Любая стратегия будет работать. Стратегия 1, вероятно, будет достаточно быстрой (ошибка на стороне пространства).

1 голос
/ 07 января 2009

Как часто вы запускаете селекторы в таблице? Являются ли выборки частью обычной обработки или больше для отчетности и / или обслуживания и отладки?

Есть ли начальная загрузка данных? Если нет, то размер таблицы будет крошечным и, вероятно, останется таким на долгие годы.

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

Я бы, вероятно, просто оставил таблицу как есть и запустил профилировщик, чтобы увидеть, как осуществляется доступ к таблице в производственной среде. Если это будет таблица, к которой обращаются постоянно и которая может стать узким местом для различных функций, тогда я бы предпочла, какие столбцы будут частью предложения WHERE наиболее часто, и добавила бы в нее один индекс. Например, если есть процесс, который просматривает все события за последние 24 часа и который запускается каждые 10 секунд, тогда может быть в порядке индекс по столбцу даты, и я бы даже кластеризовал его, а не первичный ключ. 1007 *

0 голосов
/ 07 января 2009

Пожалуйста, взгляните на эту хорошую статью об индексировании SQL Server:

http://www.mssqltips.com/tip.asp?tip=1206

0 голосов
/ 07 января 2009

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

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