Индекс (базы данных)
Индекс (англ. index) — объект базы данных, создаваемый с целью повышения производительности поиска данных. Таблицы в базе данных могут иметь большое количество строк, которые хранятся в произвольном порядке, и их поиск по заданному критерию путём последовательного просмотра таблицы строка за строкой может занимать много времени. Индекс формируется из значений одного или нескольких столбцов таблицы и указателей на соответствующие строки таблицы и, таким образом, позволяет искать строки, удовлетворяющие критерию поиска. Ускорение работы с использованием индексов достигается в первую очередь за счёт того, что индекс имеет структуру, оптимизированную под поиск — например, сбалансированного дерева.
Некоторые СУБД расширяют возможности индексов введением возможности создания индексов по столбцам представлений[1] или индексов по выражениям.[2] Например, индекс может быть создан по выражению upper(last_name)
и соответственно будет хранить ссылки, ключом к которым будет значение поля last_name
в верхнем регистре. Кроме того, индексы могут быть объявлены как уникальные и как неуникальные. Уникальный индекс реализует ограничение целостности на таблице, исключая возможность вставки повторяющихся значений.
Архитектура
[править | править код]Существует два типа индексов: кластерные и некластерные. При наличии кластерного индекса строки таблицы упорядочены по значению ключа этого индекса. Если в таблице нет кластерного индекса, таблица называется кучей[3]. Некластерный индекс, созданный для такой таблицы, содержит только указатели на записи таблицы. Кластерный индекс может быть только одним для каждой таблицы, но каждая таблица может иметь несколько различных некластерных индексов, каждый из которых определяет свой собственный порядок следования записей.
Индексы могут быть реализованы различными структурами. Наиболее часто употребимы B*-деревья, B+-деревья, B-деревья и хеши.
Последовательность столбцов в составном индексе
[править | править код]Последовательность, в которой столбцы представлены в составном индексе, достаточно важна. Дело в том, что получить набор данных по запросу, затрагивающему только первый из проиндексированных столбцов, можно. Однако в большинстве СУБД невозможно или неэффективно получение данных только по второму и далее проиндексированным столбцам (без ограничений на первый столбец).
Например, представим себе телефонный справочник, отсортированный вначале по городу, затем по фамилии, и затем по имени. Если вы знаете город, вы можете легко найти все телефоны этого города. Однако в таком справочнике будет весьма трудоёмко найти все телефоны, записанные на определённую фамилию — для этого необходимо посмотреть в секцию каждого города и поискать там нужную фамилию. Некоторые СУБД выполняют эту работу, остальные же просто не используют такой индекс.
Производительность
[править | править код]Для оптимальной производительности запросов индексы обычно создаются на тех столбцах таблицы, которые часто используются в запросах. Для одной таблицы может быть создано несколько индексов. Однако увеличение числа индексов замедляет операции добавления, обновления, удаления строк таблицы, поскольку при этом приходится обновлять сами индексы. Кроме того, индексы занимают дополнительный объём памяти, поэтому перед созданием индекса следует убедиться, что планируемый выигрыш в производительности запросов превысит дополнительную затрату ресурсов компьютера на сопровождение индекса.
Ограничения
[править | править код]Индексы полезны для многих приложений, однако на их использование накладываются ограничения. Возьмём такой запрос SQL:
SELECT first_name FROM people WHERE last_name = 'John Doe';
Для выполнения такого запроса без индекса СУБД должна проверить поле last_name
в каждой строке таблицы (этот механизм известен как «полный перебор» или «полное сканирование таблицы», в плане может отображаться словом NATURAL). При использовании индекса СУБД просто проходит по B-дереву, пока не найдёт запись «John Doe». Такой проход требует гораздо меньше ресурсов, чем полный перебор таблицы.
Теперь возьмём такой запрос:
SELECT email_address FROM customers WHERE email_address LIKE '%@yahoo.com';
Этот запрос должен нам найти всех клиентов, у которых е-мейл заканчивается на @yahoo.com
, однако даже если по столбцу email_address
есть индекс, СУБД всё равно будет использовать полный перебор таблицы. Это связано с тем, что индексы строятся в предположении, что слова/символы идут слева направо. Использование символа подстановки в начале условия поиска исключает для СУБД возможность использования поиска по B-дереву. Во многих СУБД эта проблема может быть решена созданием дополнительного индекса по выражению reverse(email_address)
и формированием запроса вида:
SELECT email_address FROM customers WHERE reverse(email_address) LIKE reverse('%@yahoo.com');
В данном случае символ подстановки окажется в самой правой позиции (moc.oohay@%
), что не исключает использование индекса по reverse(email_address)
.
Разрежённый и плотный индекс
[править | править код]В общем виде, индекс в базах данных — это файл с последовательностью пар ключей и указателей.[4] Идея использования индексов пришла от того, что современные базы данных слишком массивны и не помещаются в основную память. Мы обычно делим данные на блоки и размещаем данные в памяти поблочно. Однако поиск записи в БД может занять много времени. С другой стороны, файл индексов или блок индексов намного меньше блока данных и может поместиться в буфере основной памяти, что увеличивает скорость поиска записи.
Разрежённый индекс (англ. sparse index) характеризуется тем, что каждый ключ ассоциируется с определённым указателем на блок в сортированном файле данных.
Плотный индекс (англ. dense index) в свою очередь отличается тем, что каждый ключ ассоциируется с определённым указателем на запись в сортированном файле данных.
В кластерных индексах с дублированными ключами разрежённый индекс указывает на наименьший ключ в каждом блоке, в то время как плотный индекс указывает на первую запись с указанным ключом.
См. также
[править | править код]Примечания
[править | править код]- ↑ Создание индексированных представлений в MS SQL Server . Дата обращения: 10 августа 2010. Архивировано 3 декабря 2010 года.
- ↑ Использование индекса для выражений в ORDER BY (PostgreSQL) . Дата обращения: 18 августа 2011. Архивировано 27 сентября 2011 года.
- ↑ Структуры кучи в MS SQL Server . Дата обращения: 10 августа 2010. Архивировано 24 марта 2011 года.
- ↑ Hector Garcia-Molina, Jeffrey D. Ullman, Jennifer D. Widom. Database Systems: The Complete Book. — 2-е изд. — Prentice Hall, 2008. — 1248 p. — ISBN 978-0131873254.