Первое, что вы должны знать, это то, что индексы - это способ избежать сканирования полной таблицы, чтобы получить результат, который вы ищете.
Существуют разные виды индексов, и они реализованы на уровне хранилища, поэтому между ними нет стандарта, и они также зависят от используемого вами механизма хранилища.
InnoDB и индекс дерева B +
Для InnoDB наиболее распространенным типом индекса является индекс на основе B + Tree, в котором элементы хранятся в отсортированном порядке. Кроме того, вам не нужно обращаться к реальной таблице, чтобы получить индексированные значения, что делает ваш запрос более быстрым.
«Проблема» в этом типе индекса заключается в том, что вы должны запросить крайнее левое значение, чтобы использовать индекс. Итак, если в вашем индексе есть два столбца, скажем, 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
поле.
Заворачивать
Некоторые факты, которые вы можете учитывать каждый раз, когда хотите поговорить об оптимизации:
Целочисленное сравнение намного быстрее, чем сравнение строк. Это можно проиллюстрировать на примере об эмуляции хеш-индекса в InnoDB
.
Возможно, добавление дополнительных шагов в процесс делает его быстрее, а не медленнее. Это может быть проиллюстрировано тем фактом, что вы можете оптимизировать a SELECT
, разделив его на два этапа, сделав первый из них, сохраняя значения во вновь созданной таблице в памяти, а затем выполняя более сложные запросы для этой второй таблицы.
В MySQL есть и другие индексы, но я думаю, что B + Tree один из наиболее используемых когда-либо, и хэш-это полезно знать, но другие можно найти в документации MySQL .
Я настоятельно рекомендую вам прочитать книгу «High Performance MySQL», ответ на которую был определенно основан на главе об индексах.