Как работает индексирование в SQL и какие преимущества оно дает?
Когда вы индексируете столбцы, вы выражаете намерение запросить индексированные столбцы в условных выражениях, таких как запросы на равенство или диапазон. С помощью этой информации механизм хранения может построить структуру, которая делает такие запросы быстрее, часто упорядочивая их в древовидных структурах. B-деревья являются наиболее распространенными, но существует множество различных структур, таких как индексы хеш-функции, индексы R-деревьев для пространственных данных и т. Д. Каждая структура специализируется на поиске определенного типа. Например, хеш-индексы очень быстро выполняются для условий равенства, таких как:
SELECT * FROM example_table WHERE type = "example";
SELECT * FROM example_table WHERE id = X;
B-деревья также достаточно быстры для поиска равенства, но их главная сила в том, что они поддерживают запросы диапазона:
SELECT * FROM example_table WHERE id > 5 AND id < 10
SELECT * FROM example_table WHERE type = "example" and value > 25
Однако ОЧЕНЬ важно, когда вы строите индексы B-дерева, чтобы понять, что дерево упорядочено «слева направо». Т.е., если вы строите индекс B-дерева (давайте назовем его A) для {type, value}, тогда вам НУЖНО иметь условие для столбца типа, чтобы запрос мог использовать индекс. Пример индекса НЕ может использоваться в запросе, где условие зависит исключительно от значения.
Кроме того, если вы смешиваете равенство и условие диапазона, убедитесь, что столбцы равенства перечислены в индексе first , в противном случае индекс может использоваться только частично.
Какая причина для не индексации?
Если селективность индекса низкая, то при просмотре таблицы вы вряд ли сильно выиграете. скажем, например, что у вас есть индекс в поле под названием пол. Тогда селективность этого индекса будет низкой, так как поиск по этому индексу вернет половину строк исходной таблицы. Вы можете прочитать довольно простое объяснение избирательности здесь и причины этого: http://mattfleming.com/node/192
Кроме того, поддержание индекса имеет свою стоимость. Для каждой манипуляции с данными для индекса может потребоваться реструктуризация. Поэтому желательно, чтобы количество индексов было минимально необходимым для обеспечения высокой эффективности запросов к этой таблице.
В чем разница между индексированием одного столбца и индексированием нескольких столбцов?
Еще раз, это зависит от типа ваших запросов. Индексирование пола одного столбца не может быть хорошей идеей, так как селективность низкая. Когда селективность высока, тогда такой индекс имеет гораздо больший смысл. Например, индексы первичного ключа являются очень хорошим индексом, поскольку селективность высока (на самом деле, она настолько высока, насколько она получает. Каждый ключ в индексе соответствует точно в записи), а индексы в столбцах имеют уникальный или высокий уровень. различные значения (такие как slugs, хэши паролей и что нет) также являются хорошими индексами в одном столбце.
Существует также концепция покрытия индексов. По сути, каждый лист в индексе содержит указатель на таблицу, в которой хранится строка (если только индекс не является кластеризованным индексом. В этом случае лист является записью). Таким образом, для каждого попадания в индекс механизм запросов должен извлекать соответствующую строку таблицы, увеличивая количество операций ввода-вывода. Так как ввод / вывод очень медленный, вы хотите свести это к минимуму. Теперь предположим, что вам часто нужно что-то запрашивать, а также извлекать дополнительные столбцы, после чего вы можете создать закрывающий индекс, торговое пространство для хранения запросов. Пример: Давайте найдем имя и адрес электронной почты всех пользователей, которые присоединились за последние 6 месяцев (при условии MySQL):
С индексом {join_at}:
SELECT first_name, last_name, email
FROM users
WHERE joined_at > NOW() - INTERVAL 6 MONTH;
Объяснение запроса:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE users ALL test NULL NULL NULL 873 Using where
Как видно из столбца type
, механизм запросов прибегал к полному сканированию таблицы, поскольку селективность индекса была слишком низкой, чтобы ее можно было использовать в этом запросе (слишком много результатов будет возвращено и, следовательно, будет выполнено в таблицу, слишком дорого обходится при вводе / выводе)
С индексом {join_at, first_name, last_name, email}:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE users range test,test2 test2 8 NULL 514 Using where;
Using index
Теперь, поскольку вся информация, необходимая для выполнения запроса, доступна в индексе, механизм запросов оценивает, что гораздо лучше использовать индекс (с 514 строками) вместо полного сканирования таблицы.Итак, как вы можете видеть, используя закрывающие индексы, мы можем ускорить запросы для частичного выбора таблицы, даже если селективность индекса довольно мала.