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