Сколько индексов базы данных слишком много?

109

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

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

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

Итак, сколько индексов считается слишком большим? 10? 25? 50? Или я должен просто осветить действительно, действительно общие и очевидные случаи и игнорировать все остальное?

Эли Кортрайт
источник

Ответы:

87

Это зависит от операций, которые происходят на столе.

Если есть много SELECT и очень мало изменений, индексируйте все, что хотите ... это (потенциально) ускорит выполнение операторов SELECT.

Если таблица сильно поражена операциями UPDATE, INSERT + DELETE ... это будет очень медленным с большим количеством индексов, поскольку все они должны быть изменены каждый раз, когда выполняется одна из этих операций.

Сказав это, вы можете явно добавить много бессмысленных индексов в таблицу, которая ничего не сделает. Добавление индексов B-Tree в столбец с двумя разными значениями будет бессмысленным, поскольку он ничего не добавляет с точки зрения поиска данных. Чем уникальнее значения в столбце, тем больше пользы от индекса.

cagcowboy
источник
1
Чтобы уточнить, индекс по 2 значениям может быть не бессмысленным в конкретном случае, когда одно значение встречается редко, и вы хотите его найти. Так что дело не в том, насколько уникальны значения, а в том, насколько селективен индекс.
charlie_pl
44

Обычно я поступаю так.

  1. Получите журнал реальных запросов, выполняемых к данным в течение обычного дня.
  2. Добавьте индексы, чтобы наиболее важные запросы попадали в индексы в своем плане выполнения.
  3. Старайтесь избегать индексирования полей, в которых много обновлений или вставок.
  4. После нескольких индексов получите новый журнал и повторите.

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

Скливвз
источник
26

Все остальные давали вам отличный совет. У меня есть для вас дополнительное предложение по мере вашего продвижения. В какой-то момент вам нужно принять решение о лучшей стратегии индексации. В конце концов, лучшая ПЛАНОВАЯ стратегия индексирования все равно может привести к созданию индексов, которые в конечном итоге не будут использоваться. Одна из стратегий, позволяющая находить неиспользуемые индексы, - это отслеживать использование индексов. Вы делаете это следующим образом: -

alter index my_index_name monitoring usage;

Затем вы можете отслеживать, используется ли индекс с этого момента, запросив v $ object_usage. Информацию об этом можно найти в Руководстве администратора базы данных Oracle® .

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

Майк Макаллистер
источник
14

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

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

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

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

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

Дэвид Олдридж
источник
Так много на самом деле? Я бы предположил, что вы собираетесь сказать «измерение». Это довольно странный вариант использования. Но как администратор базы данных вы молодцы, так что я скажу, что мне явно чего-то не хватает.
Стефани Пейдж
@Stephanie, у нас очень похожий сценарий ... Дэвид упомянул, что это индексы растровых изображений. Мы также используем индексы BITMAP JOIN. Да, по фактам. Oracle может выполнять очень эффективные операции И с индексами растровых изображений. Например, у вас может быть предложение WHERE с 5 атрибутами с низкой мощностью, каждый из которых имеет индекс растрового изображения. Если вы посмотрите на план выполнения, он будет иметь операции И с растровым изображением (в основном это эффективные растровые изображения и операции), а затем вниз по плану выполнения вы увидите преобразование растровых изображений в идентификаторы строк. Это действительно быстро.
Tagar
12

Перефразируя Эйнштейна о простоте, добавьте столько указателей, сколько вам нужно, и не более.

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

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

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

Йозеф
источник
1
Согласен на переоценку. Хорошее администрирование никогда не бывает задачей «поставил и забыл». Изменения программного обеспечения. Требования меняются. Изменения в использовании. Новая, казалось бы, тривиальная функциональность, представленная в один прекрасный день, может быстро стать вашим самым большим узким местом, а вчерашний краеугольный код хлеба с маслом может стать бездействующим и ненужным жиром, который просто зависает, потребляя ресурсы. Я также согласен с итеративным подходом. Если вы сделаете слишком много сразу, вы не узнаете, что сработало.
durette
6

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

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

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

WW.
источник
Я проголосовал за, но ... Я бы сказал, что дополнительное время на синтаксический анализ, хотя и интересно и академично, никогда не повлияет на мой выбор правильного количества индексов. согласна?
Стефани Пейдж
@StephaniePage Я не проводил экспериментов, чтобы что-то доказать. Однако я видел проект, который наивно создавал одностолбцовый индекс для каждого столбца. Если в некоторых таблицах есть 80 столбцов, я думаю, это может начать оказывать влияние. Oracle, похоже, учитывает стоимость доступа по каждому индексу. Но да, я согласен, есть более важные вещи, которые нужно учитывать, чем это.
WW.
Ммм ... Я считаю, что существует максимальное количество времени, которое Oracle потратит на жесткий синтаксический анализ ... рассмотрим SQL с более чем несколькими таблицами, скажем 7 или 8, выбор одного только порядка соединения может генерировать сотни возможных пути доступа.
Стефани Пейдж
6

Я провел несколько простых тестов на своем реальном проекте и реальной базе данных MySql. Я уже отвечал в этой теме: какова стоимость индексации нескольких столбцов db?

Но я думаю, будет лучше, если я процитирую это здесь:

Я провел несколько простых тестов, используя свой настоящий проект и настоящую базу данных MySql.

Мои результаты: добавление среднего индекса (1-3 столбца в индексе) к таблице - замедляет вставку на 2,1%. Итак, если вы добавите 20 индексов, ваши вставки будут медленнее на 40-50%. Но ваш выбор будет в 10-100 раз быстрее.

Так можно ли добавлять много индексов? - Как много :) Я привел вам свои результаты - решать вам!

nightcoder
источник
Это не следует воспринимать как пророчество без всех подробностей. Тем более, что вы не можете умножить прирост / потерю производительности от одного действия к другому. Основа остается прежней: добавьте больше индексов, и ваши вставки в конечном итоге будут медленнее из-за воссоздания индекса.
SovietFrontier
3

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

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

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

Орион Адриан
источник
3

На мой взгляд, статичного ответа нет, такие вещи относятся к «настройке производительности».

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

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

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

Для SQL Server я нашел полезным советник по настройке ядра СУБД - вы настраиваете «типичные» рабочие нагрузки, и он может давать рекомендации по добавлению / удалению индексов и статистики. Я уверен, что в других БД есть аналогичные инструменты, будь то «официальные» или сторонние.

Scotta
источник
3

Это действительно более теоретические вопросы, чем практические. Влияние индексов на вашу производительность зависит от оборудования, которое у вас есть, версии Oracle, типов индексов и т. Д. Вчера я услышал, что Oracle анонсировала выделенное хранилище от HP, которое должно работать в 10 раз быстрее с базой данных 11g. В вашем случае может быть несколько решений: 1. Имейте большое количество индексов (> 20) и перестраивайте их ежедневно (каждую ночь). Это было бы особенно полезно, если таблица получает тысячи обновлений / удалений ежедневно. 2. Разбейте таблицу на разделы (если это применимо к вашей модели данных). 3. Используйте отдельную таблицу для новых / обновленных данных и запускайте ночной процесс, который объединяет данные вместе. Это потребует изменения логики вашего приложения. 4. Переключитесь на IOT (индексированная таблица), если ваши данные это поддерживают.

Конечно, для такого случая может быть еще много решений. Моим первым предложением было бы клонировать БД в среду разработки и провести с ней стресс-тестирование.

Моше
источник
Я не понимаю, как поможет восстановление индексов или как поможет IOT.
Дэвид Олдридж,
IOT - если есть возможность перепроектировать приложение так, чтобы использовался новый тип данных, определенный пользователем, то IOT сэкономит накладные расходы на индексацию таблицы. здесь может быть не так. это действительно зависит. перестроение индекса - если индексов много, а новые данные не индексируются.
Моше
IOT по-прежнему является индексной структурой с большими накладными расходами на разбиение блоков, чем обычный индекс. «перестроение индекса - в случае, если индексов много, а новые данные не проиндексированы» ... о какой СУБД вы говорите, которая не поддерживает автоматически индексы для новых записей?
Дэвид Олдридж,
Дэвид - ты, конечно, прав. Я смешал это с возможностью SQL Server индексировать полнотекстовый поиск только по запросу. Хотелось бы, чтобы он был у Oracle, поскольку он может быть полезен в этом случае. Я бы рекомендовал придерживаться двух других предложений.
Моше
2

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

Боб Кинг
источник
2

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

Джеффри Л. Уитледж
источник
2

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

Сможете ли вы выдержать дополнительное время, необходимое для завершения обновления?

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

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

Уолтер Митти
источник
1

Сколько там столбцов? Мне всегда говорили делать индексы с одним столбцом, а не с несколькими столбцами. Так что индексов не больше, чем количество столбцов, ИМХО.

Ламкро
источник
1

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

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

Торбьорн Гюллебринг
источник
1

Сервер Sql предоставляет вам несколько хороших инструментов, которые позволяют увидеть, какие индексы фактически используются. В этой статье http://www.mssqltips.com/tip.asp?tip=1239 вы найдете несколько запросов, которые позволят вам лучше понять, насколько используется индекс, а не насколько он обновляется.

aboy021
источник
0

Он полностью основан на столбцах, которые используются в предложении Where. И как большой палец правила, мы должны иметь индексы по столбцам внешнего ключа, чтобы избежать мертвых блокировок. Отчет AWR следует периодически анализировать, чтобы понимать необходимость индексов.

П. Шарма
источник
2
Индексы столбцов внешнего ключа, чтобы избежать взаимоблокировок? У вас есть ссылка, объясняющая, почему и как это происходит?
Джей Салливан