Когда создавать новый индекс SQL Server? - PullRequest
15 голосов
/ 30 октября 2008

Очевидно (метки), создание индекса для столбца BIT не требуется. Однако, если у вас есть столбец, в котором нужно искать, в котором каждое значение, вероятно, уникально, например, BlogPost или StreetAddress или что-то еще, тогда индекс кажется подходящим (опять же, метинкс).

Но что за отсечка? Что делать, если вы ожидаете 10000 строк и у вас будет около 20 уникальных значений среди них. Нужно ли создавать индекс?

Заранее спасибо.

Ответы [ 9 ]

17 голосов
/ 30 октября 2008

Лучший ответ на это - профилировать ваши запросы и посмотреть, улучшит ли индекс ваши запросы. Трудность в ответе на это состоит в том, что почти невозможно обобщить поведение оптимизатора запросов.

Тем не менее, эмпирическое правило гласит: если ваша избирательность составляет 10% или менее для данного запроса к таблице, тогда вы, скорее всего, выиграете от индекса. Так что в вашем примере вы могли бы воспользоваться индексом, если ваши значения распределены равномерно. Однако, учитывая, что у вас маленький стол, прирост производительности может быть незначительным.

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

Также имейте в виду, что при вставке в таблицу с индексом значительно снижается производительность Если эта таблица часто обновляется или добавляется, увеличение скорости из индекса может быть сведено на нет медленными вставками и обновлениями.

См. Статью MSDN по Просмотр таблиц и доступ к индексам .

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

2 голосов
/ 09 ноября 2008

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

Пример. У меня была таблица с полем «Состояние», в котором принимались только значения «A», «N» и «R» (для «Активный», «Новый» и «Вышедший».) 95% были "R", 4 +% были "A", и некоторые были "N". SELECT WHERE state = 'N' будет сканировать таблицу, несмотря ни на что.

НО - есть новый тип индекса, называемый Filtered Index, , который, наконец, обрабатывает это условие. Это также удобно, когда вы хотите исключить записи со значениями NULL.

2 голосов
/ 30 октября 2008

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

1 голос
/ 30 октября 2008

создание индекса для столбца BIT не требуется.

Вы были бы удивлены.

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

SELECT foo.Name FROM foo WHERE foo.Active = 1

Хотя в таблице было около 300 000 строк.

1 голос
/ 30 октября 2008

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

Все столбцы внешнего ключа должны быть проиндексированы.

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

0 голосов
/ 25 октября 2014

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

С Вы используете DMV с отсутствующим индексом SQL?

SELECT
  migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,
  'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle)
  + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']'
  + ' ON ' + mid.statement
  + ' (' + ISNULL (mid.equality_columns,'')
    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END
    + ISNULL (mid.inequality_columns, '')
  + ')'
  + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement,
  migs.*, mid.database_id, mid.[object_id]
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC
0 голосов
/ 15 сентября 2013

одним из лучших способов является использование mvp-представлений в SQL Server. я не могу перезапустить ваш сервер на одну неделю, а затем выполнить этот запрос:

USE master; 
Go
SELECT d.database_id,
  d.object_id,
  d.index_handle,
  d.equality_columns,
  d.inequality_columns,
  d.included_columns,
  d.statement AS fully_qualified_object,
  gs.*
FROM   sys.dm_db_missing_index_groups g
JOIN   sys.dm_db_missing_index_group_stats gs ON   gs.group_handle = g.index_group_handle
JOIN   sys.dm_db_missing_index_details d ON   g.index_handle = d.index_handle

Go

SELECT mig.index_group_handle,
  mid.index_handle,
  migs.avg_total_user_cost AS AvgTotalUserCostThatCouldbeReduced,
  migs.avg_user_impact AS AvgPercentageBenefit,
  'CREATE INDEX missing_index_' + CONVERT (varchar, mig.index_group_handle)
  + '_' + CONVERT (varchar, mid.index_handle)
  + ' ON ' + mid.statement
  + ' (' + ISNULL (mid.equality_columns,'')
  + CASE
         WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns
         IS NOT NULL THEN ','
         ELSE ''
    END
    + ISNULL (mid.inequality_columns, '')
  + ')'
  + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS  create_index_statement
FROM sys.dm_db_missing_index_groups mig 
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle =  mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle =  mid.index_handle
Order By migs.avg_user_impact Desc

, затем проверьте ваши таблицы и создайте индекс запроса.

0 голосов
/ 09 ноября 2008

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

0 голосов
/ 09 ноября 2008

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

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

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