Какие столбцы обычно составляют хорошие индексы?

98

В продолжение темы « Что такое индексы и как я могу использовать их для оптимизации запросов в моей базе данных? », Где я пытаюсь узнать об индексах, какие столбцы являются хорошими кандидатами на индекс? Специально для базы данных MS SQL?

После некоторого поиска в Google все, что я прочитал, предполагает, что столбцы, которые обычно увеличиваются и уникальны, создают хороший индекс (такие как MySQL auto_increment), я понимаю это, но я использую MS SQL, и я использую GUID для первичных ключей, поэтому кажется что индексы не принесут пользы столбцам GUID ...

mmattax
источник
Как насчет «кулинарной книги»: mysql.rjweb.org/doc.php/index_cookbook_mysql
Рик Джеймс

Ответы:

110

Индексы могут играть важную роль в оптимизации запросов и быстром поиске результатов из таблиц. Поэтому наиболее важным шагом является выбор столбцов для индексации. Есть два основных места, где мы можем рассмотреть возможность индексирования: столбцы, указанные в предложении WHERE, и столбцы, используемые в предложениях JOIN. Короче говоря, должны быть проиндексированы такие столбцы, по которым вы должны искать определенные записи. Предположим, у нас есть таблица с именем Buyers, в которой запрос SELECT использует индексы, как показано ниже:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Так как "идентификатор покупателя" упоминается в части SELECT, MySQL не будет использовать его для ограничения выбранных строк. Следовательно, нет особой необходимости его индексировать. Ниже приведен еще один пример, немного отличающийся от приведенного выше:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

Согласно приведенным выше запросам столбцы first_name, last_name могут быть проиндексированы, поскольку они расположены в предложении WHERE. Также для индексации можно рассмотреть дополнительное поле country_id из таблицы стран, поскольку оно находится в предложении JOIN. Таким образом, индексацию можно рассматривать для каждого поля в предложении WHERE или JOIN.

В следующем списке также есть несколько советов, которые вы всегда должны иметь в виду, когда собираетесь создавать индексы в своих таблицах:

  • Индексируйте только те столбцы, которые требуются в предложениях WHERE и ORDER BY. Обильная индексация столбцов приведет к некоторым недостаткам.
  • Попробуйте воспользоваться функцией MySQL «индексный префикс» или «многостолбцовый индекс». Если вы создаете индекс, такой как INDEX (first_name, last_name), не создавайте INDEX (first_name). Однако использование «префикса индекса» или «индекса с несколькими столбцами» не рекомендуется во всех случаях поиска.
  • Используйте атрибут NOT NULL для тех столбцов, в которых вы рассматриваете индексацию, чтобы значения NULL никогда не сохранялись.
  • Используйте параметр --log-long-format для регистрации запросов, не использующих индексы. Таким образом, вы можете изучить этот файл журнала и соответствующим образом скорректировать свои запросы.
  • Оператор EXPLAIN помогает вам понять, как MySQL будет выполнять запрос. Он показывает, как и в каком порядке объединяются таблицы. Это может быть очень полезно для определения того, как писать оптимизированные запросы и нужно ли индексировать столбцы.

Обновление (23 февраля 2015 г.):

Любой индекс (хороший / плохой) увеличивает время вставки и обновления.

В зависимости от ваших индексов (количества индексов и типа) ищется результат. Если ваше время поиска увеличится из-за индекса, то это плохой индекс.

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

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

Сомнатх Мулук
источник
Спасибо, Somnath, значит ли это, что индексы должны создаваться только для столбцов, которые мы планируем использовать WHERE, JOINSили HAVING?
Мухаммад Бабар
3
Да, используйте индексы для столбцов, в которых вы планируете использовать WHERE, JOINS или HAVING. Но также имейте в виду, что все столбцы условий не требуют индексов. Иногда, когда столбец условий используется только один раз, поэтому ему может не понадобиться индекс, тогда как другой столбец условий используется во многих запросах, поэтому предпочитайте больше для индексации этого столбца.
Сомнатх Мулук
1
Для ответа было бы полезно поместить "столбцы, указанные в предложении WHERE, и столбцы, используемые в предложениях JOIN" в разделе TL; DR.
jpmc26
Итак, вы говорите, что если в моем WHEREпредложении я проверяю значение поля, столбец которого может принимать только два значения, то я должен проиндексировать этот двоичный столбец? Это кажется неправильным.
AjaxLeung
@AjaxLeung: Помните изречение Кнута «Преждевременная оптимизация - корень всего зла». Вы можете сделать индекс для двоичных столбцов, но это должно зависеть от того, по какой цене (например, вставка, время обновления). Если ваша бизнес-логика часто зависит от этого двоичного переключателя, то может потребоваться, чтобы двоичный столбец имел индекс.
Somnath Muluk
20

Некоторые люди ответили здесь на аналогичный вопрос: как узнать, что такое хороший индекс?

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

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

Удачи!

SquareCog
источник
9

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

Индексы будут полезны, если:

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

Они не пригодятся, если:

  • Вы выбираете большой% (> 10-20%) строк в таблице
  • Дополнительное использование места - проблема
  • Вы хотите добиться максимальной производительности пластин. Каждый индекс в таблице снижает производительность вставки и обновления, поскольку они должны обновляться каждый раз при изменении данных.

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

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

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

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

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

(Прошу прощения, если я повторяю вещи, упомянутые в вашем другом вопросе, я не сталкивался с этим раньше.)

Zooba
источник
5

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

Сюда входят: внешние ключи -

select * from tblOrder where status_id=:v_outstanding

описательные поля -

select * from tblCust where Surname like "O'Brian%"

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

select * from tblOrder where paidYN='N'
папа
источник
Ваше явное упоминание внешних ключей действительно прояснило для меня вопрос о присоединении.
pfabri
3

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

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

Джванагель
источник
3

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

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

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

Ясень
источник
Ну, это не совсем так. Вы можете легко создать обычный некластеризованный индекс для столбца GUID - почему бы и нет? GUID имеет большой недостаток, если вы используете его в качестве ключа кластеризации (например, для КЛАСТЕРИРОВАННОГО ИНДЕКСА) - тогда его использование будет ужасным.
marc_s
1

Старым практическим правилом были столбцы, которые часто используются в предложениях WHERE, ORDER BY и GROUP BY, или те, которые, казалось, часто используются в соединениях. Имейте в виду, что я имею в виду индексы, а НЕ первичный ключ

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

реванш
источник
1

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

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

Иви
источник
1

Числовые типы данных, упорядоченные в порядке возрастания или убывания, являются хорошими индексами по нескольким причинам. Во-первых, числа обычно вычисляются быстрее, чем строки (varchar, char, nvarchar и т. Д.). Во-вторых, если ваши значения не упорядочены, может потребоваться перетасовка строк и / или страниц для обновления индекса. Это дополнительные накладные расходы.

Если вы используете SQL Server 2005 и настроили использование uniqueidentifiers (guids), и вам НЕ нужно, чтобы они имели случайный характер, проверьте последовательный тип uniqueidentifier.

Наконец, если вы говорите о кластерных индексах, вы говорите о виде физических данных. Если у вас есть строка в качестве кластерного индекса, это может стать некрасивым.

Ян Саттл
источник
0

Это должно быть еще быстрее, если вы используете GUID. Предположим, у вас есть записи

  1. 100
  2. 200
  3. 3000
  4. ....

Если у вас есть индекс (бинарный поиск, вы можете найти физическое местоположение записи, которую ищете, за время O (lg n), вместо последовательного поиска O (n) времени). Это потому, что вы не знаете, какие записи у вас есть в вашем столе.

Милхаус
источник
0

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

Взято для примера База данных участников с первичным ключом номера социального страхования участников. Мы выбираем SS, потому что приложение priamry таким образом относится к человеку, но вы также хотите создать функцию поиска, которая будет использовать имя и фамилию участников. Затем я бы предложил создать индекс по этим двум полям.

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

Джозеф
источник