Индексирование с самого начала или когда возникает проблема производительности?

15

Мой вопрос касается использования индексов.

  1. Должен ли я начать индексирование с самого начала или когда возникает проблема с производительностью?

  2. Мы также можем создать временный индекс при выполнении запроса. Каковы плюсы и минусы таких методов?

codecool
источник

Ответы:

17

Должен ли я начать индексирование с самого начала или когда возникает проблема с производительностью?

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

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

  • Создайте свои основные и другие уникальные ограничения . Они будут обеспечены уникальными индексами.

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

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

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

Не редкая проблема в кругах SQL Server заключается в чрезмерной индексации в результате указаний из отсутствующих указателей DMV и подсказок SSMS. Ни один из этих инструментов не оценивает существующие индексы и будет рад предложить вам создать новый индекс из 6 столбцов, а не добавлять один столбец в существующий индекс из 5 столбцов.

-- If you have this
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
)

-- But your query would benefit from the addition of a column
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

-- SSMS will suggest you create this instead
CREATE NONCLUSTERED INDEX [IX_MyTable_AnotherIndexWithTheSameColumnsAsTheExistingIndexPlusCol6] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

Кимберли Трипп (Kimberly Tripp) обладает отличным материалом по стратегии индексирования, который, в то время как сфокусированный на SQL, применим для других платформ. Для разработчиков SQL Server есть несколько удобных инструментов для идентификации дубликатов, как в примере выше.

Мы также можем создать временный индекс при выполнении запроса. Каковы плюсы и минусы таких методов?

Обычно это относится только к редко запускаемым запросам, обычно к ETL. Вам необходимо оценить:

  1. Сокращает ли время, затрачиваемое на создание индекса, время выполнения запроса.
  2. Затраты на обслуживание, связанные с сохранением индекса, перевешивают время, затрачиваемое на создание / удаление, когда это необходимо.
Марк Стори-Смит
источник
3
+1 ключ кластеризации, внешний ключ, уникальный / первичный ключ и недоверчивость отсутствующих индексных DMV по номинальной стоимости ... Все эти вещи - отличный совет. Работа с существующими индексами в SQL Server довольно легко отслеживать с помощью DMV sys.dm_db_index_usage_stats. За определенный период времени вы можете перечислить индексы, которые не были отсканированы или найдены, а также увидеть, что эти же индексы обновлялись несколько раз. Это свидетельствует о чрезмерной индексации.
Мэтт М
1
+1, однако «создайте индексы для любых явно избирательных запросов». не охватывает все другие сценарии. Индексы могут помочь в сортировке результатов, даже если ваши запросы не очень избирательны. Они также могут ускорить запросы, если они охватывают все выбранные столбцы.
причины
1
Согласились, но вопрос был в том, чтобы искать точку отсчета, а не конец игры. Определить запросы, которые нужно охватить, сложно без шаблонов использования, поскольку вы можете редко охватывать их все.
Марк Стори-Смит
8

Там действительно риски, связанные с обоими подходами:

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

Вам нужно будет дисциплинировать себя, чтобы идентифицировать индексы, которые больше не используются, и попытаться удалить их (PostgreSQL может сделать это; к сожалению, MySQL в сравнении очень слаб в этом из коробки).

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

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

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


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

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

Морган Токер
источник
4

В дополнение к ответу Марка

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

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

Конечно, я видел странную проблему только в производстве из-за моделей использования, когда все остальное идентично

Временные индексы? Вне шаблонов загрузки ETL, если они вам понадобятся один раз, они понадобятся вам снова. Не забывайте: создание / удаление индекса - это запись и запись в журнал = больше нагрузки

ГБН
источник
3

Просто чтобы добавить несколько вещей.

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

Это мой подход.

  1. Подобно Марку, создавайте индексы там, где они имеют смысл, но не запаздывайте.
  2. Вам не нужно ждать, пока производительность снизится, чтобы создать новые индексы. Всякий раз, когда вы пишете новый SQL, запускайте план запросов (желательно к вашей базе данных prod). Вы должны увидеть, требуется ли новый индекс.
  3. Не бойтесь ставить > 0или > ""в ваших пунктах where неиспользуемые столбцы.

    1. То есть, допустим, у вас есть индекс A, B, C и D. Однако у вас есть только информация A, B, D. Нет причин, по которым ты не можешь
    select * from blah 
    where A="one" 
    and B="two" 
    and C>=""     --to match index
    and D="four"
    
    --This will use your existing index. No need to create a redundant one.
user606723
источник
Другое дело, это на форуме "dba", но за создание индекса должны отвечать разработчики, а не dba. (Для случаев, когда они полностью разделены.)
user606723
2
Ваше утверждение относительно пространства, занимаемого индексами, немного вводит в заблуждение, поскольку в некластеризованном индексе накладных расходов очень мало. Если бы вы могли опубликовать вопрос по этому вопросу, стоило бы изучить его дальше. Во-вторых, я не согласен с тем, что создание индекса является доменом разработчика. Это одна из областей, где сотрудничество между разработчиком и администратором базы данных может дать наилучшие результаты.
Марк Стори-Смит
1
Я приведу вам пример одной из наших таблиц. Размер стола: 21052404 КБ. Размер одного некластеризованного индекса в этой таблице: 6637470 КБ. Очень мало накладных расходов? Думаю, нет. Кроме того, я не говорю, что с администраторами баз данных не следует сотрудничать, я говорю, что ответственность за определение необходимости создания нового индекса должна быть на стороне разработчика. Они не должны писать SQL и ожидать, что dbas сам это выяснит.
user606723
1
Вы не можете цитировать такие числа без контекста. Без указания столбцов индекса NC и кластеризованного ключа невозможно вычислить долю накладных расходов по сравнению с данными.
Марк Стори-Смит
Touche. Ключом является [числовой (24), символ, дата], а столбцами ЧПУ являются [дата, числовой (24)]. (Всего два столбца в этом конкретном индексе).
user606723
2

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

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

Мэриан
источник