Это преждевременная оптимизация для добавления индексов базы данных?

61

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

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

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

Марко де Йонг
источник
32
Это может быть вопросом мнения, однако я чувствую, что некоторые индексы могут быть добавлены априори.
Василий Старынкевич,
2
@BasileStarynkevitch Полностью согласен с тем, что у нас уже есть индексы первичного ключа и все работает. Но где вы проводите черту?
Марко де Йонг,
1
Мои два цента из опыта: я тестировал некоторые из моих ранних поисковых запросов в подмножестве нашей базы данных. Тесты, которые я проводил, были полностью хороши на моей локальной копии. Затем я перенес приложение в промежуточную область, в которой размещена полная база данных. Мои тесты выполнялись в течение <500 мс , в то время как постановка системы заняла несколько минут . Мой начальник был полностью сбит с толку тем, почему приложение не загружается. Объясните операции с типами - ваш друг ... По крайней мере, ищите последовательные сканы на больших таблицах, по крайней мере!
Крис Cirefice
2
Не добавлять индексы - все равно что использовать пузырьковую сортировку. Чаще всего вы не обнаружите никаких проблем при тестировании, но как только ваша программа начнет расширяться, вы столкнетесь с целым рядом проблем. И индексы могут легко составить коэффициент разницы в 100 раз.
Питер Б
3
Просто всегда помните: индекс - это не волшебная вещь, которая ускорит ваши запросы. Индекс будет нести расходы на большинство операций DML и в зависимости от типа может привести к большим ожиданиям, когда многие люди обновляют одну и ту же таблицу. Для запросов: Есть много запросов, которые не получают никакой выгоды от индекса, где FTS является самым быстрым или где Секционирование выполняет всю работу за вас. - Только добавьте индекс, где вы ЗНАЕТЕ, что они будут полезны!
Falco

Ответы:

132

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

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

Мейсон Уилер
источник
11
Да, это должно быть сделано на этапе нагрузочного тестирования
Alvaro
152
Оптимизация до того, как вы узнаете, где медленные части, является преждевременной оптимизацией. Освобождение объекта до того, как вы узнаете, где находятся медленные части, преждевременное освобождение !
Математическая
4
@MatumaticOrchid: Это отличная формулировка! Могу ли я взять его в другом месте?
Питер Гиркенс
3
@PieterGeerkens Конечно, вышибись! ;-) Мне просто грустно, что 91+ upvotes не приносит мне никакой репутации ... хех.
Математическая
3
@MateticOrchid должен был быть ответ. Может баллотироваться на «самый маленький прямой ответ» когда-либо.
Миндвин
48

следить за медленными запросами, как только мы начнем жить

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

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

gbjbaanb
источник
10
Правильно. Рассматривайте индексы как часть дизайна базы данных. Используйте индексы, чтобы избежать полного сканирования таблицы для любого запроса, который обычно будет выполнять конечный пользователь в режиме реального времени.
AE
1
@DocBrown Я не уверен, что когда вы разрабатываете таблицу, у вас есть (или должно быть) понимание того, как она будет использоваться. Персональная таблица будет запрашиваться по ID или, возможно, по фамилии. Если кто-то начинает получать доступ через DoB, адрес или номер телефона, вы собираетесь добавить индексы для каждого поля - и где это заканчивается ?!
gbjbaanb
4
@gbjbaanb: заканчивается, когда люди перестают добавлять функции в продукт, что может быть «никогда» в зависимости от вашей методологии.
Стив Джессоп
1
@SteveJessop Я имею в виду, что вы индексируете в соответствии с основными столбцами, к которым вы хотите получить доступ. Для персональной таблицы у вас может быть функция поиска (если вы забыли свое имя пользователя, вы можете искать по электронной почте, например), но после этого вы всегда будете использовать идентификатор. Таким образом, ID является единственным, который нуждается в индексации. Если вы выполняете большой поиск в других полях, вам может потребоваться индекс, это произойдет вовремя, но, как правило, вы не хотите индексировать каждый столбец только потому, что кто-то когда-то решил написать нестандартный запрос, но вы можете использовать другой механизм для этих «разовых» случаев.
gbjbaanb
2
@gbjbaanb: конечно, люди не должны повторно искать одну и ту же фамилию в таблице, потому что она является чуть более удобным для них дескриптором, чем надлежащий ключ для таблицы. Я бы сказал, что это так, независимо от того, индексируется ли таблица по фамилии или нет, поскольку в коде есть что-то очень подозрительное, предполагающее, что все работает на «одном и том же пользователе», но не может это выразить в коде, запоминая идентификатор :-) Я представлял себе случаи, когда необходимость обратного просмотра не ожидалась, пока клиент не упомянул об этом ...
Стив Джессоп
26

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

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

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

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

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

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

Стив Джессоп
источник
20

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

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

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

Какова ваша общая нагрузка ?

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

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

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

Но...

Некоторые заходят слишком далеко и сходят с ума, добавляя индексы «на всякий случай». Кто-то рекомендует это пропущенный индекс? Добавьте его и четыре других варианта. Также плохая идея. Вам нужно не только подумать о поиске данных, но и об изменении данных? Чем больше индексов у вас в таблице, вообще говоря, тем больше накладных расходов у вас при изменении данных.

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

В качестве забавного небольшого примечания стороны ... Множественное число "Индекса"

«Индексы» для финансовых людей

«Индексы» для нас

Томас Стрингер
источник
2
Это требует больше голосов. Я не мог согласиться больше.
RubberDuck
+1 за бит «на всякий случай» (это было бы преждевременной оптимизацией). Если бы я мог, я бы снова высказался за бит "общая рабочая нагрузка".
Дэвид
Надеюсь, вы заранее знаете, какие 10 запросов принадлежат 98%, а какие нет.
Паŭло Эберманн
@ PaŭloEbermann Большинство СУБД имеют возможность быстро и легко собирать эту информацию. В этом случае нет никаких оправданий для незнания.
Томас Стрингер
@ThomasStringer Конечно, это работает только в том случае, если ваши тестовые примеры перед началом работы связаны с тем, что делают реальные пользователи в производстве.
Паŭло Эберманн
4

Нет, это не преждевременная оптимизация, но это должно быть сделано правильно, как и любая оптимизация.

Вот что я бы сделал:

  1. Загрузите базу данных с достаточным количеством тестовых данных, чтобы имитировать производственную нагрузку. Вы не можете получить это на 100% точно, но это хорошо: просто введите достаточно данных. У одной таблицы есть фиксированный объем данных? Загрузите это. У вас есть одна таблица, которая содержит много данных, например, какая таблица содержит вопросы на этом сайте? Загрузите несколько миллионов записей, даже если это просто фиктивные данные.
  2. Включите профилирование на вашем сервере базы данных.
  3. Ударьте по приложению, используя комбинацию автоматизированных сценариев (обеспечивает объем) и реальных пользователей (они знают, как сломать вещи).
  4. Просмотрите данные профилирования. Являются ли конкретные запросы медленными? Проверьте планы объяснения и посмотрите, говорит ли сервер базы данных, что он хочет индекс, но он не существует.

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

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


источник
3

Следование проверенным схемам известных проблем (например, поиск записи по ее идентификатору) не является преждевременным. Это просто разумно.

Тем не менее, индексы не всегда простой бизнес. Зачастую на этапе проектирования сложно определить, от каких индексов будет зависеть ваш трафик, а какие будут препятствовать операциям записи. Итак, я бы поспорил за использование некоторых «очевидных» передовых методов проектирования схем (используйте PK, соответствующий разработанным шаблонам чтения / записи и индексным FK); но не ставьте индекс ни на что другое, пока ваше стресс-тестирование не потребует этого.

svidgen
источник
Потратить дополнительные 30 секунд на то, что почти наверняка улучшит производительность и вряд ли повредит, это не «преждевременная оптимизация». Если в 90% операций над таблицей в качестве ключа используется определенный столбец, то или его индексация повысит производительность, или производительность никогда не будет достаточно медленной, и добавление кода для создания индекса может занять меньше времени, чем определение того, действительно необходимо.
суперкат
@supercat "never" ... Пока вы не начнете видеть тупики в своей производственной среде ...
svidgen
Какие реалистичные сценарии, по вашему мнению, будут соответствовать 90% операций, использующих столбец в качестве ключа, и где добавление индекса приведет к взаимоблокировке?
суперкат
@supercat Я не уверен, что полностью понимаю ваш квест. С точки зрения активного приложения, практически любое увеличение времени выполнения или количества операций ввода-вывода может привести к возникновению взаимоблокировок. ... Более того, наличие или отсутствие индекса в большинстве приложений незначительно, пока база данных не достигнет критического размера и / или уровня параллелизма. Например, когда все ваши индексы больше не помещаются в памяти ...
svidgen
1
Дело в том, что сложно понять, как устроен ваш запрос, пока типичные сценарии использования не пройдут стресс-тестирование (или пока вы не увидите проблемы с неожиданным поведением пользователя на производстве). Если у вас есть страница с ключами от tablex.fieldy, но она удаляется только один раз на каждую тысячу вставок ... Индекс может привести к ухудшению сети.
svidgen
2

Когда ваше приложение будет выпущено, будет слишком поздно.

Но любой правильный процесс разработки должен включать тестирование производительности.

Используйте результаты ваших тестов производительности, чтобы решить, какие индексы добавить, и проверьте их эффективность, повторив тесты производительности.

Philipp
источник
Когда приложение выходит, это действительно хорошее время для подстройки индексов. Посмотрите на этот сайт, stachexchange, вы можете поспорить, что ваши индексы изменились долгое время после того, как он вышел в эфир.
LosManos
@LosManos: никто не платит за использование Stack Exchange.
Легкость гонок с Моникой
@LightnessRacesinOrbit: С другой стороны, рекламодатели платят за использование Stack Exchange.
@JonofAllTrades: им все равно, если у нас будет несколько часов плохой работы из-за отсутствия индекса. Я хочу сказать, что большой бесплатный веб-сайт, ориентированный на сообщество, с постоянным циклом распространения сильно отличается от периодически выпускаемого автономного коммерческого продукта. Таким образом, SE не является хорошим примером.
Легкость гонки с Моникой
1

Хотя я не думаю, что каждый запрос должен быть оптимизирован, индексы являются настолько важной частью СУРБД, что их необходимо учитывать перед выпуском. Когда вы выполняете запрос, в отличие от других форм программирования, вы не говорите системе, как его выполнить. Они разрабатывают собственные планы и почти всегда основывают его на наличии индекса. Состав и объем данных будут рассмотрены также в более позднее время.

Вот некоторые вещи, которые я хотел бы рассмотреть:

  1. Есть некоторые запросы, которые вы должны определить в начале своей разработки, которые, как вы знаете, будут часто использоваться. Сосредоточиться на них.
  2. Будут медленные запросы. Индексируя их сначала, вы можете определить, все еще ли производительность не достаточно быстра, а затем рассмотреть возможность перепроектирования (денормализация может быть преждевременной). Я бы предпочел сделать это перед выпуском. Никто не хочет систему, где требуется 10 минут, чтобы найти что-то в инвентаре.
  3. Индексы могут улучшить производительность запросов, но они не должны препятствовать модификации данных.
  4. Во многих системах есть инструменты для анализа ваших запросов, поэтому не бойтесь их использовать.

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

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

JeffO
источник
0

Это также зависит от того, сколько пользователей вы ожидаете. Вам определенно следует провести нагрузочное тестирование и убедиться, что ваша база данных может поддерживать от 10 до 100 с до 1000 с одновременных запросов. Опять же, это зависит от того, сколько трафика вы ожидаете, и какие области вы ожидаете использовать больше, чем другие.

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

harsimranb
источник
0

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

Вот некоторые вопросы, которые вам нужно задать:

  • Каковы пределы дизайна для размера каждой таблицы?

Если таблицы всегда будут маленькими (скажем, <100 строк), то не беда, если база данных будет сканировать всю таблицу. Может быть полезно добавить индекс, но это требует немного большего опыта или измерения, чтобы определить.

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

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

  • Требует ли запрос поиска таблицы по чему-то помимо первичного ключа? Например, фильтрация по диапазону дат, присоединение по внешнему ключу?

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

user611910
источник