Как работают индексы MySQL? - PullRequest
376 голосов
/ 25 августа 2010

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

Это не по теме, я знаю, но если есть кто-то, кто мог быобъясните мне это подробно, я был бы очень, очень благодарен.

Ответы [ 5 ]

485 голосов
/ 25 августа 2010

В основном индекс таблицы работает как индекс в книге (отсюда и название):

Допустим, у вас есть книга о базах данных, и вы хотите найти некоторую информацию, скажем, о хранилище. Без индекса (при условии отсутствия другой помощи, такой как оглавление) вам пришлось бы просматривать страницы одну за другой, пока вы не найдете тему (это full table scan). С другой стороны, в индексе есть список ключевых слов, поэтому вы можете просмотреть его и увидеть, что storage упоминается на страницах 113-120, 231 и 354. Затем вы можете переходить на эти страницы напрямую, без поиска (это поиск по индексу, несколько быстрее).

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

  • если бы у вас была книга о базах данных и было проиндексировано слово «база данных», вы бы увидели, что она упоминается на страницах 1–59, 61–290 и 292–400. В этом случае индекс не очень помогает и, возможно, было бы быстрее пролистывать страницы одну за другой (в базе данных это «плохая избирательность»).
  • Для 10-страничной книги не имеет смысла создавать индекс, поскольку в итоге вы можете получить 10-страничную книгу с префиксом 5-страничного индекса, что просто глупо - просто отсканируйте 10 страниц и покончено с этим.
  • Индекс также должен быть полезен - обычно нет смысла индексировать, например, частота буквы «L» на странице.
242 голосов
/ 10 января 2013

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

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

InnoDB и индекс B + Tree

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

«Проблема» в этом типе индекса заключается в том, что вам нужно запросить крайнее левое значение, чтобы использовать индекс. Итак, если ваш индекс имеет два столбца, скажем, last_name и first_name, порядок, в котором вы запрашиваете эти поля , имеет большое значение .

Итак, с учетом следующей таблицы:

CREATE TABLE person (
    last_name VARCHAR(50) NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    INDEX (last_name, first_name)
);

Этот запрос будет использовать индекс:

SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"

Но следующий не будет

SELECT last_name, first_name FROM person WHERE first_name = "Constantine"

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

Последний пример еще хуже:

SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"

Потому что теперь вы сравниваете самую правую часть самого правого поля в индексе.

Хеш-индекс

Это другой тип индекса, который, к сожалению, поддерживает только внутренняя память. Это молниеносно, но полезно только для полных поисков, что означает, что вы не можете использовать его для таких операций, как >, < или LIKE.

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

Если у вас есть большое поле VARCHAR, вы можете «эмулировать» использование хеш-индекса при использовании B-дерева, создав другой столбец и сохранив на нем хеш большого значения. Допустим, вы храните URL-адрес в поле, а значения довольно большие. Вы также можете создать целочисленное поле с именем url_hash и использовать хеш-функцию, например CRC32, или любую другую хеш-функцию для хеширования URL-адреса при его вставке. И затем, когда вам нужно запросить это значение, вы можете сделать что-то вроде этого:

SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");

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

SELECT url FROM url_table 
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";

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

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

Завершение

Некоторые факты, которые вы можете учитывать каждый раз, когда хотите поговорить об оптимизации:

  1. Сравнение целых чисел намного быстрее, чем сравнение строк. Это можно проиллюстрировать на примере об эмуляции хеш-индекса в InnoDB.

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

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

Я настоятельно рекомендую вам прочесть книгу "High Performance MySQL", ответ выше был определенно основан на главе об индексах.

35 голосов
/ 25 августа 2010

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

1: перейти к середине списка - выше или ниже того, что я ищу?

2: если выше, перейти на полпути между серединой и низом, если ниже, посередине и сверху

3: выше или ниже? Снова перейти к средней точке и т. Д.

Используя эту логику, вы можете найти элемент в отсортированном списке примерно за 7 шагов вместо проверки каждого элемента.

Очевидно, что есть сложности, но это дает вам основную идею.

4 голосов
/ 25 августа 2010

Посмотрите по этой ссылке: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

То, как они работают, слишком широко для темы, чтобы освещать ее в одном посте.

Здесь является одним из лучших объяснений индексов, которые я видел. К сожалению, это для SQL Server, а не MySQL. Я не уверен, насколько они похожи ...

3 голосов
/ 19 апреля 2017

Возьмите это видео для более подробной информации об индексировании

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

CREATE UNIQUE INDEX index_name
ON table_name ( column1, column2,...);

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

CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author)

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

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

mysql> CREATE UNIQUE INDEX AUTHOR_INDEX
ON tutorials_tbl (tutorial_author DESC)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...