Как работает индексация базы данных?

Учитывая, что индексирование так важно, поскольку ваш набор данных увеличивается в размере, может ли кто-нибудь объяснить, как индексирование работает на уровне, не зависящем от базы данных?

Информацию о запросах для индексации поля см. В статье Как индексировать столбец базы данных .

Ответов (8)

Решение

Зачем это нужно?

Когда данные хранятся на дисковых устройствах хранения, они хранятся в виде блоков данных. Доступ к этим блокам осуществляется полностью, что делает их операцией доступа к атомарному диску. Блоки дисков имеют такую ​​же структуру, как и связанные списки; оба содержат раздел для данных, указатель на расположение следующего узла (или блока), и оба не должны храниться непрерывно.

В связи с тем, что ряд записей может быть отсортирован только по одному полю, мы можем заявить, что для поиска в несортированном поле требуется линейный поиск, который требует N/2 доступа к N блокам (в среднем), где - количество блоков, которые стол пролетает. Если это поле не является ключевым полем (т.е. не содержит уникальных записей), то при N доступе блока необходимо выполнить поиск во всем табличном пространстве .

Принимая во внимание, что с отсортированным полем может использоваться двоичный поиск, который имеет log2 N блочный доступ. Кроме того, поскольку данные сортируются по неключевому полю, остальная часть таблицы не нуждается в поиске повторяющихся значений, как только будет найдено более высокое значение. Таким образом, прирост производительности существенный.

Что такое индексация?

Индексирование - это способ сортировки ряда записей по нескольким полям. Создание индекса для поля в таблице создает другую структуру данных, которая содержит значение поля и указатель на запись, к которой оно относится. Затем эта структура индекса сортируется, что позволяет выполнять двоичный поиск по ней.

Обратной стороной индексации является то, что эти индексы требуют дополнительного места на диске, поскольку индексы хранятся вместе в таблице с использованием механизма MyISAM, этот файл может быстро достичь пределов размера базовой файловой системы, если проиндексировано много полей в одной таблице. .

Как это работает?

Во-первых, давайте набросаем образец схемы таблицы базы данных;

Имя поля Тип данных Размер на диске
id (Первичный ключ) Беззнаковое INT 4 байта
firstName Char (50) 50 байт
lastName Char (50) 50 байт
emailAddress 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 блокам.

Для линейного поиска по полю id потребуется среднее количество N/2 = 500,000 обращений к блоку для нахождения значения, учитывая, что поле id является ключевым полем. Но поскольку поле 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 доступов к блокам, это далеко от 1000000 блочных доступов, необходимых для поиска совпадения firstName в неиндексированной таблице.

Когда его следует использовать?

Учитывая, что для создания индекса требуется дополнительное дисковое пространство (277 778 блоков больше из приведенного выше примера, увеличение на ~ 28%), и что слишком большое количество индексов может вызвать проблемы, связанные с ограничениями размера файловых систем, необходимо тщательно продумать выбор правильного поля для индексации.

Поскольку индексы используются только для ускорения поиска совпадающего поля в записях, понятно, что поля индексации, используемые только для вывода, были бы просто пустой тратой дискового пространства и времени обработки при выполнении операции вставки или удаления, и, следовательно, необходимо избегать. Также, учитывая характер двоичного поиска, важна мощность или уникальность данных. Индексирование поля с числом элементов 2 разделит данные пополам, тогда как число элементов 1000 вернет примерно 1000 записей. С такой низкой мощностью эффективность сводится к линейной сортировке, и оптимизатор запросов избегает использования индекса, если мощность меньше 30% от номера записи, что фактически делает индекс пустой тратой пространства.

Индекс - это просто структура данных, которая ускоряет поиск определенного столбца в базе данных. Эта структура обычно представляет собой b-дерево или хеш-таблицу, но может быть любой другой логической структурой.

Просто подумайте об указателе базы данных как об указателе книги.

Если у вас есть книга о собаках и вы хотите найти информацию, скажем, о немецких овчарках, вы, конечно, можете пролистать все страницы книги и найти то, что ищете, но это, конечно, отнимает много времени, а не очень быстро.

Другой вариант заключается в том, что вы можете просто перейти к разделу указателя книги, а затем найти то, что вы ищете, используя имя объекта, который вы ищете (в данном случае, немецкие овчарки), а также посмотрев номер страницы для быстро найди то, что ищешь.

В базе данных номер страницы называется указателем, который направляет базу данных на адрес на диске, где находится объект. Используя ту же аналогию с немецкой овчаркой, мы могли бы получить что-то вроде этого («German Shepherd», 0x77129), где 0x77129 - адрес на диске, где хранятся данные строки для немецкой овчарки.

Короче говоря, индекс - это структура данных, в которой хранятся значения для определенного столбца в таблице, чтобы ускорить поиск запроса.

Просто быстрое предложение. Поскольку индексация требует дополнительных операций записи и хранения, поэтому, если вашему приложению требуется больше операций вставки / обновления, вы можете использовать таблицы без индексов, но если для этого требуется больше операций извлечения данных, вам следует перейти на индексированные стол.

Простое описание!

Индекс - это не что иное, как структура данных, в которой хранятся значения определенного столбца в таблице. Индекс создается по столбцу таблицы.

Пример: у нас есть таблица базы данных User с тремя столбцами - Name, Age и Address . Предположим, что в User таблице тысячи строк.

Теперь предположим, что мы хотим запустить запрос, чтобы найти все сведения о любых пользователях с именем «Джон». Если мы запустим следующий запрос:

SELECT * FROM User 
WHERE Name = 'John'

Программное обеспечение базы данных должно буквально просматривать каждую строку в User таблице, чтобы увидеть, является ли Name для этой строки значением «Джон». Это займет много времени.

Здесь index нам помогает: индекс используется для ускорения поисковых запросов за счет существенного сокращения количества записей / строк в таблице, которые необходимо изучить .

Как создать индекс:

CREATE INDEX name_index
ON User (Name)

index Состоит из значений столбцов (например: Джон) из одной таблицы , и эти значения сохраняются в структуре данных .

Итак, теперь база данных будет использовать индекс для поиска сотрудников по имени Джон, потому что индекс предположительно будет отсортирован в алфавитном порядке по имени пользователя. А поскольку оно отсортировано, это означает, что поиск имени выполняется намного быстрее, потому что все имена, начинающиеся с «J», будут располагаться в индексе рядом друг с другом!

Теперь предположим, что мы хотим запустить запрос, чтобы найти все подробности о любых сотрудниках с именем «Abc»?

SELECT * FROM Employee 
WHERE Employee_Name = 'Abc'

Что было бы без индекса?

Программное обеспечение базы данных должно буквально просматривать каждую отдельную строку в таблице Employee, чтобы увидеть, является ли Employee_Name для этой строки «Abc». И поскольку мы хотим, чтобы каждая строка с именем «Abc» внутри нее, мы не можем просто перестать искать, как только мы найдем только одну строку с именем «Abc», потому что могут быть другие строки с именем Abc . Таким образом, каждая строка до последней строки должна быть найдена - это означает, что тысячи строк в этом сценарии должны быть проверены базой данных, чтобы найти строки с именем «Abc». Это то, что называется полным сканированием таблицы

Как индекс базы данных может повысить производительность

Весь смысл наличия индекса состоит в том, чтобы ускорить поисковые запросы, существенно сократив количество записей / строк в таблице, которые необходимо изучить. Индекс - это структура данных (чаще всего B-дерево), в которой хранятся значения для определенного столбца в таблице.

Как работает индекс B-деревьев?

Причина, по которой B-деревья являются самой популярной структурой данных для индексов, заключается в том, что они экономят время, потому что поиск, удаление и вставка могут выполняться за логарифмическое время. И еще одна важная причина, по которой B-деревья используются чаще, заключается в том, что данные, которые хранятся внутри B-дерева, можно сортировать. РСУБД обычно определяет, какая структура данных фактически используется для индекса. Но в некоторых сценариях с некоторыми СУБД вы можете фактически указать, какую структуру данных вы хотите, чтобы ваша база данных использовала при создании самого индекса.

Как работает индекс хеш-таблицы?

Причина, по которой используются хеш-индексы, заключается в том, что хеш-таблицы чрезвычайно эффективны, когда дело доходит до простого поиска значений. Таким образом, запросы, которые сравнивают на равенство со строкой, могут очень быстро извлекать значения, если они используют хеш-индекс.

Например, для запроса, который мы обсуждали ранее, может быть полезен хеш-индекс, созданный в столбце Employee_Name. Способ работы хеш-индекса заключается в том, что значение столбца будет ключом в хэш-таблице, а фактическое значение, сопоставленное с этим ключом, будет просто указателем на данные строки в таблице. Поскольку хеш-таблица в основном представляет собой ассоциативный массив, типичная запись будет выглядеть примерно так: «Abc => 0x28939 ″, где 0x28939 - это ссылка на строку таблицы, в которой Abc хранится в памяти. Поиск такого значения, как «Abc» в индексе хэш-таблицы, и возврат ссылки на строку в памяти, очевидно, намного быстрее, чем сканирование таблицы для поиска всех строк со значением «Abc» в столбце Employee_Name.

Недостатки хеш-индекса

Хеш-таблицы - это не отсортированные структуры данных, и есть много типов запросов, с которыми хеш-индексы даже не могут помочь. Например, предположим, что вы хотите узнать всех сотрудников младше 40 лет. Как вы могли сделать это с помощью индекса хеш-таблицы? Что ж, это невозможно, потому что хеш-таблица хороша только для поиска пар ключ-значение, что означает запросы, которые проверяют равенство

Что именно находится внутри индекса базы данных? Итак, теперь вы знаете, что индекс базы данных создается для столбца в таблице и что индекс хранит значения в этом конкретном столбце. Но важно понимать, что индекс базы данных не сохраняет значения в других столбцах той же таблицы. Например, если мы создаем индекс для столбца Employee_Name, это означает, что значения столбца Employee_Age и Employee_Address также не сохраняются в индексе. Если бы мы просто сохранили все остальные столбцы в индексе, это было бы похоже на создание еще одной копии всей таблицы, которая занимала бы слишком много места и было бы очень неэффективно.

Как база данных узнает, когда использовать индекс? Когда выполняется запрос типа «SELECT * FROM Employee WHERE Employee_Name = 'Abc'», база данных проверяет, есть ли индекс в запрашиваемых столбцах. Предполагая, что столбец Employee_Name имеет индекс, созданный для него, базе данных необходимо будет решить, действительно ли имеет смысл использовать индекс для поиска значений, в которых выполняется поиск, - потому что есть некоторые сценарии, когда на самом деле менее эффективно использовать индекс базы данных. , и более эффективно просто сканировать всю таблицу.

Какова стоимость индекса базы данных?

Он занимает место - и чем больше ваша таблица, тем больше ваш индекс. Еще одним ударом по производительности с индексами является тот факт, что всякий раз, когда вы добавляете, удаляете или обновляете строки в соответствующей таблице, те же операции должны выполняться с вашим индексом. Помните, что индекс должен содержать те же самые данные с точностью до минуты, что и все, что находится в столбцах таблицы, которые охватывает индекс.

Как правило, индекс следует создавать для таблицы только в том случае, если данные в индексируемом столбце будут запрашиваться часто.

Смотрите также

  1. Какие столбцы обычно составляют хорошие индексы?
  2. Как работают индексы базы данных

Классический пример «Указатель в книгах»

Рассмотрим «Книгу» из 1000 страниц, разделенную на 10 глав, каждый раздел по 100 страниц.

Все просто, да?

Теперь представьте, что вы хотите найти конкретную главу, которая содержит слово « алхимик ». Без индексной страницы у вас нет другого выбора, кроме как сканировать всю книгу / главы. то есть: 1000 страниц.

Эта аналогия известна как «Полное сканирование таблицы» в мире баз данных.

введите описание изображения здесь

Но с индексной страницей вы знаете, куда идти! И более того, чтобы найти какую-либо конкретную важную главу, вам просто нужно каждый раз просматривать индексную страницу снова и снова. Найдя соответствующий индекс, вы можете быстро перейти к этой главе, пропустив остальные.

Но тогда, помимо фактических 1000 страниц, вам понадобится еще ~ 10 страниц для отображения индексов, то есть всего 1010 страниц.

Таким образом, индекс представляет собой отдельный раздел, в котором хранятся значения индексированного столбца + указатель на индексированную строку в отсортированном порядке для эффективного поиска.

В школах все просто, не правда ли? :П

Когда я впервые прочитал это, мне это очень помогло. Спасибо.

С тех пор я получил некоторое представление о недостатках создания индексов: если вы пишете в таблицу ( UPDATE или INSERT ) с одним индексом, у вас фактически две операции записи в файловой системе. Один для данных таблицы, а другой - для данных индекса (и их пересортировка (и - если кластеризована - пересортировка данных таблицы)). Если таблица и индекс расположены на одном жестком диске, это требует больше времени. Таким образом, таблица без индекса (куча) позволит быстрее выполнять операции записи. (если бы у вас было два индекса, вы бы получили три операции записи и т. д.)

Однако определение двух разных мест на двух разных жестких дисках для данных индекса и данных таблиц может уменьшить / устранить проблему увеличения затрат времени. Это требует определения дополнительных групп файлов с соответствующими файлами на желаемых жестких дисках и определения местоположения таблицы / индекса по желанию.

Еще одна проблема с индексами - их фрагментация с течением времени при вставке данных. REORGANIZE помогает, вы должны написать процедуры, чтобы это было сделано.

В определенных сценариях куча более полезна, чем таблица с индексами,

например: - Если у вас много конкурирующих записей, но только одно чтение в ночное время в нерабочее время для отчетности.

Кроме того, очень важно различать кластерные и некластеризованные индексы.

Помогло мне: - Что на самом деле означает кластерный и некластеризованный индекс?