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

когда я должен использовать индекс на таблице?

  1. от сколько строк индекс имеет смысл?
  2. Если у меня есть таблица с постоянными строками, просто отредактированные столбцы come (не в предложении "где"), имеет смысл индекса, даже если таблица имеет всего около 15 строк? EDIT: может ли в таком случае неиндексный выбор/чтение быть более эффективным, чем чтение индекса?

изменить: Теперь я работаю с firebird 2.5, но большую часть времени я использую SQL Server 2005/2008.

5 ответов


В общем, моя стратегия индексирования будет примерно такой (я использую SQL Server исключительно сейчас-адаптируйтесь к вашей собственной системе баз данных по мере необходимости):

  • выберите хороший ключ кластеризации-не GUID, не VARCHAR(250) или что-то - а хороший ключ кластеризации узкий, уникальный, стабильный, постоянно увеличивающийся - что-то вроде INT IDENTITY идеально подходит. Делает это ваш кластеризованный первичный ключ -> дает вам ваш первый индекс таблица

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

и на этом все.

затем: запустите свою систему-наблюдайте и измеряйте - установите базовую линию. Является ли приложение достаточно быстрым? Если да - > вы закончили-идите домой и наслаждайтесь свободным временем.

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

Если у вас есть улучшение -> оставьте этот индекс на месте, и это измерение является вашей новой базовой линией. Промойте и повторяйте, пока вы (и ваши пользователи) не будете довольны производительностью приложения (и затем идите домой и наслаждайтесь своим свободным временем).

чрезмерная индексация в SQL Server может быть хуже чем отсутствие индексов. Не начинать слишком много индексов для начала! Только установить хороший кластеризованные PK и некластеризованные индексы внешнего ключа-Вот и все - затем наблюдайте, измеряйте, оптимизируйте и повторяйте этот цикл.


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

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

Если вы используете SQL Server, вы можете запустить трассировку с помощью SQL Server profiler, чтобы помочь вам

EDIT:

может быть в таком случае неиндексный выбор / чтение более эффективным, чем индекс читать?

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


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

некоторые упоминали о принятии базовой линии, используя какую-то утилиту трассировки для измерения производительности и т. д. Если вы в порядке с установленной производительностью, двигайтесь дальше. Если нет, проанализируйте план выполнения, физическую модель данных (доступные индексы), пересчитайте статистику и посмотрите, помогает ли оптимизатор выбрать лучший план выполнения. Убедитесь, что СУБД может (разрешено) использовать доступную ОЗУ. Попробуйте минимизировать дисковый ввод - вывод и так далее на.

в случае Firebird 2.5 недавно добавленный API трассировки Firebird является находкой. Теперь Вы, наконец, можете получить трассировку в реальном времени о том, что выполняется против базы данных со счетчиками производительности (план выполнения, время выполнения, статистика ввода-вывода ...). И сторонний продукт под названием FB TraceManager by Upscene Productions делает API трассировки радостью для использования.


Что касается второй части вашего вопроса, если таблица имеет только 15 строк, это очень вероятно, что независимо от того, сколько индексов на таблице всегда будет проверять, потому что это настолько маленькое.


Я использую этот запрос для получения подсказки о том, какая из моих таблиц нуждается в индексе:

-- Missing Indexes for current database by Index Advantage  (Query 57) (Missing Indexes)
SELECT DISTINCT CONVERT(decimal(18,2), user_seeks * avg_total_user_cost * (avg_user_impact * 0.01)) AS [index_advantage], 
migs.last_user_seek, mid.[statement] AS [Database.Schema.Table],
mid.equality_columns, mid.inequality_columns, mid.included_columns,
migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact,
OBJECT_NAME(mid.[object_id]) AS [Table Name], p.rows AS [Table Rows]
FROM sys.dm_db_missing_index_group_stats AS migs WITH (NOLOCK)
INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (NOLOCK)
ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details AS mid WITH (NOLOCK)
ON mig.index_handle = mid.index_handle
INNER JOIN sys.partitions AS p WITH (NOLOCK)
ON p.[object_id] = mid.[object_id]
WHERE mid.database_id = DB_ID() 
ORDER BY index_advantage DESC OPTION (RECOMPILE);

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