Зачем это нужно?
Когда данные хранятся на дисковых устройствах хранения, они хранятся в виде блоков данных. Доступ к этим блокам осуществляется полностью, что делает их операцией доступа к атомарному диску. Дисковые блоки структурированы во многом так же, как связанные списки; оба содержат раздел для данных, указатель на местоположение следующего узла (или блока), и оба не должны храниться непрерывно.
В связи с тем, что несколько записей могут быть отсортированы только по одному полю, мы можем констатировать, что поиск по несортированному полю требует линейного поиска, который требует N/2
обращения к N
блокам (в среднем), где число блоков, которое таблица охватывает. Если это поле является неключевым (то есть не содержит уникальных записей), тогда все табличное пространство необходимо искать при N
доступе к блоку.
Принимая во внимание, что с отсортированным полем может использоваться Бинарный поиск, который имеет log2 N
доступ к блоку. Кроме того, поскольку данные сортируются по неключевому полю, в остальной части таблицы не нужно искать дубликаты значений, как только будет найдено более высокое значение. Таким образом, увеличение производительности является существенным.
Что такое индексация?
Индексирование - это способ сортировки нескольких записей по нескольким полям. Создание индекса для поля в таблице создает другую структуру данных, которая содержит значение поля и указатель на запись, к которой он относится. Затем эта структура индекса сортируется, что позволяет выполнять бинарный поиск.
Недостатком индексации является то, что эти индексы требуют дополнительного места на диске, так как индексы хранятся вместе в таблице с использованием механизма MyISAM, этот файл может быстро достичь пределов размера базовой файловой системы, если проиндексировано много полей в одной таблице. ,
Как это работает?
Во-первых, давайте наметим пример схемы таблицы базы данных;
Имя поля Тип данных Размер на диске
id (первичный ключ) INT без знака 4 байта
firstName Char (50) 50 байтов
lastName Char (50) 50 байтов
emailАдрес Char (100) 100 байт
Примечание : вместо varchar использовался символ char для точного определения размера диска. Этот образец базы данных содержит пять миллионов строк и не индексируется. Производительность нескольких запросов теперь будет проанализирована. Это запрос с использованием идентификатора (поле отсортированного ключа) и запрос с использованием firstName (не отсортированное по ключу поле).
Пример 1 - сортировка против несортированных полей
Учитывая нашу примерную базу данных r = 5,000,000
записей фиксированного размера, дающих длину записи R = 204
байтов, и они хранятся в таблице с использованием механизма MyISAM, который использует B = 1,024
байты размера блока по умолчанию . Фактором блокировки таблицы будет количество bfr = (B/R) = 1024/204 = 5
записей на диск. Общее количество блоков, необходимых для хранения таблицы, равно N = (r/bfr) = 5000000/5 = 1,000,000
блокам.
Линейный поиск в поле идентификатора потребует среднего числа N/2 = 500,000
обращений к блоку, чтобы найти значение, учитывая, что поле идентификатора является ключевым полем. Но поскольку поле id также отсортировано, можно выполнить бинарный поиск, требующий среднего числа log2 1000000 = 19.93 = 20
обращений к блоку. Мгновенно мы видим, что это радикальное улучшение.
Теперь поле firstName не сортируется и не является ключевым, поэтому двоичный поиск невозможен, а значения не являются уникальными, и, следовательно, таблица потребует поиска в конце для точного N = 1,000,000
доступа к блоку. Именно эту ситуацию индексация стремится исправить.
Учитывая, что индексная запись содержит только индексированное поле и указатель на исходную запись, очевидно, что она будет меньше, чем многополевая запись, на которую она указывает. Таким образом, сам индекс требует меньше дисковых блоков, чем исходная таблица, поэтому для итераций требуется меньше обращений к блокам. Схема для индекса в поле firstName приведена ниже;
Имя поля Тип данных Размер на диске
firstName Char (50) 50 байтов
(указатель записи) Специальные 4 байта
Примечание . Указатели в MySQL имеют длину 2, 3, 4 или 5 байт в зависимости от размера таблицы.
Пример 2 - индексация
Приведен пример нашей базы данных r = 5,000,000
записей с индексной записью длины R = 54
байтов и использованием размера блока по умолчанию в B = 1,024
байтах. Фактором блокировки индекса будет количество bfr = (B/R) = 1024/54 = 18
записей на блок диска. Общее количество блоков, необходимых для хранения индекса, равно N = (r/bfr) = 5000000/18 = 277,778
блокам.
Теперь поиск с использованием поля firstName может использовать индекс для увеличения производительности. Это позволяет выполнять двоичный поиск по индексу со средним log2 277778 = 18.08 = 19
числом обращений к блоку. Чтобы найти адрес фактической записи, которая требует дополнительного доступа к блоку для чтения, что приводит к общему количеству 19 + 1 = 20
обращений к блокам, это далеко от 1 000 000 обращений к блокам, необходимых для поиска соответствия firstName в неиндексированной таблице.
Когда его следует использовать?
Принимая во внимание, что создание индекса требует дополнительного дискового пространства (277 778 блоков дополнительно из приведенного выше примера, увеличение ~ 28%), и что слишком много индексов могут вызвать проблемы, возникающие из-за ограничений размера файловых систем, необходимо тщательно продумать, чтобы выбрать правильный поля для индексации.
Поскольку индексы используются только для ускорения поиска соответствующего поля в записях, очевидно, что поля индексации, используемые только для вывода, будут просто пустой тратой дискового пространства и времени обработки при выполнении операции вставки или удаления, и, таким образом, необходимо избегать. Также, учитывая природу бинарного поиска, важна мощность или уникальность данных. Индексирование в поле с количеством элементов, равным 2, делит данные пополам, тогда как количество элементов в 1000 возвращает приблизительно 1000 записей. При таком низком количестве элементов эффективность снижается до линейной сортировки, и оптимизатор запросов избегает использования индекса, если количество элементов составляет менее 30% от числа записей, что фактически делает индекс пустой тратой пространства.