B+ дерево хранения данных MySql (обсуждение)

1. Фактическое место хранения MySql

Дерево B+ — это основной метод хранения структуры данных MySql, включая механизмы InnoDB и MYISAM, а их структура хранения по умолчанию — дерево B+.

Прежде чем понять дерево B+, нам нужно знать, где находится фактическое место хранения MySql?

Некоторые люди скажут, что он существует в каталоге Data папки MySql на моем диске D или C. Это правильный ответ. Давайте посмотрим поближе?

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

Физические диски обычно можно описать как: цилиндры, магнитные поверхности и сектора.Благодаря этим трем параметрам можно точно определить местоположение данных.

Давайте посмотрим на обычную магнитную поверхность:

Мы видим, что на этой магнитной поверхности записаны дорожки и сектора,

Как правило, существует два типа позиционирования диска: фиксированная головка и подвижная головка:

На каждой дорожке фиксированной головки есть головка чтения-записи, стоимость высокая, но скорость чтения-записи высокая, а время позиционирования короткое.

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

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

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

Размер сектора более широко известен как 512 байт (существует также сектор размером 2048 байт, который постепенно расширяется позже, давайте возьмем 512 байт в качестве примера здесь)

Давайте сначала просто посмотрим на таблицу данных, как данные хранятся в секторе:

 Здесь мы определяем таблицу и данные в ней, у нее три атрибута: id 8 байт, name 40 байт, no 16 байт.

Отсюда мы можем сделать вывод: запись этой таблицы занимает 8+40+16=64 байта, а запись этой таблицы, которую мы определяем сейчас, будет занимать 64 байта.

Сектор 512 байт: 512/64=8

Таким образом, один сектор может содержать только 8 записей, для наших 32 записей требуется 32/8 = 4, и нам нужно 4 сектора для загрузки,

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

Но когда мы просто добавляем записи в 800: 800/8 = 100, то есть нам нужно 100 секторов для загрузки, то нам нужно 100 операций ввода-вывода, когда мы хотим найти 800-ю запись, очевидно, такие операции ввода-вывода слишком медленно.Если 1000 человек должны искать, накладные расходы времени будут очень большими.

В этом случае нужно ввести индекс, корневые узлы B+ дерева почти все индексы

2. Индекс MySql

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

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

Проще говоря, индекс создается или добавляется позже, его можно разделить на индекс первичного ключа, составной индекс, общий индекс,

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

Здесь мы просто снова смотрим на две таблицы:

 Здесь мы видим, что таблица справа — это наша таблица данных, в которой записаны записи 800. Мы также видели выше, что для запроса требуется 100 операций ввода-вывода, поэтому мы рассматриваем возможность создания индекса для идентификатора.

Когда идентификатор выбран в качестве индекса, идентификатор будет формировать таблицу с фактическим физическим адресом, где находится идентификатор.Эта таблица имеет 8 байтов для идентификатора, 8 байтов для адреса и всего 16 байтов.Это также существует в секторе и не может быть связан с ним Исходная таблица данных находится в соседних секторах

Размер сектора 512 байт: 512/16 = 32, поэтому сектор, в котором находится индексная таблица, может содержать 32 записи.

Первая запись: идентификатор записи равен 1, ее физический адрес,

Вторая запись: идентификатор записи 33, ее физический адрес,

Тридцать вторая запись: идентификатор записи 1023, ее физический адрес

С помощью этой индексной таблицы процесс проверки данных 800 записей упрощается.

Во-первых, операция ввода-вывода проверит индексную таблицу (вам нужно использовать индекс, чтобы попасть в нее, то есть оператор условного суждения в операторе sql имеет идентификатор), и здесь только один ввод-вывод выполняется для получения информации 1~ 33, 33~65, ...~1023 в этих интервалах

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

Это лучший случай: 800-я условная запись получается за 2 ввода-вывода.

Давайте рассмотрим наихудший случай: внимательные друзья могут обнаружить, что каждый интервал имеет наихудший случай.

например:

В диапазоне 1~33, когда мы хотим запросить 32, мы можем найти только сектор с id=1, а затем читать по очереди, пока не прочитаем сектор с id=32

В диапазоне 33~65, когда мы хотим запросить 64, мы можем найти только сектор с id=33, а затем читать по очереди, пока не прочитаем сектор с id=64

......

В интервале 800~833, когда мы ищем 832:

Для нас будет найден только первый адрес 800, который является вводом-выводом для чтения и записи.

Всего читается 32 записи с 800 по 832: 32/8=4 (сектора), то есть нам нужно непрерывно читать 4 сектора, чтобы найти запись с id = 832, что требует 4 операций ввода-вывода.

Мы видим, что даже в худшем случае: 1 + 4 = 5, нам нужно всего 5 операций ввода-вывода, чтобы получить какие-либо данные.

По сравнению с запросами без индексов: начиная с 32-й записи количество операций чтения и записи будет увеличиваться пропорционально

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

Продолжайте увеличивать данные, на этот раз сохраните 80 000 записей:

Когда объем данных достигает 80 000: наша индексная таблица первого уровня (индексная таблица, близкая к фактической таблице данных, называется индексом первого уровня) становится очень слабой.

Давайте просто подсчитаем, что наша индексная таблица первого уровня может хранить только интервальные адреса 1~1025 записей, когда данные равны 80000.

80000/1024 = 78~79, нам нужно 79 секторов для хранения

Если это худший случай: мы хотим найти 80 000-ю запись, то мы выполнили 79 операций ввода-вывода в индексной таблице первого уровня, и адрес индексной таблицы первого уровня для проверки фактических данных равен 4. раз ввода-вывода, поэтому в данном случае 79+4=83 раза ввода-вывода

Для 80 000 запросов данных требуется 83 операции ввода-вывода Очевидно, что количество операций ввода-вывода слишком велико, и мы должны найти способ уменьшить количество операций ввода-вывода.

 В настоящее время наши разработчики думают о том, чтобы добавить слой, вторичный индекс указывает на первичный индекс, а первичный индекс указывает на данные.Для древовидной структуры B+ это дополнительный слой.

 Поле адреса во вторичном индексе — это адрес записанного первичного индекса, а не прямое указание на данные Во вторичном индексе оно предназначено для записи местоположения первичного сектора.

например:

Диапазон данных сектора в первичном индексе: 1~1025.

Запись вторичного индекса составляет 1 ~ 1025 интервала первичного индекса.

 Следовательно, диапазон, в котором сектор вторичного индекса может записывать диапазон первичного индекса, составляет:

1024 * 32 = 32768

Для таблицы с 80 000 записей можно разместить только 3 сектора вторичного индекса.

В это время используйте вторичный индекс для поиска 80000:

1.

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

Затем перейдите к индексу первого уровня, чтобы найти его. Поскольку это физический адрес, предоставленный индексом второго уровня, для чтения этого сектора требуется только один ввод-вывод. В индексе первого уровня есть диапазон, который 80000~81025.

Наконец, чтобы найти фактические данные, всего 80000 является указателем головы, и для завершения требуется только один ввод-вывод.

Это наилучшая ситуация: 3+1+1=5, наилучшее состояние — это 5-кратный ввод-вывод для получения данных.

 2.

В худшем случае также найти данные в индексе первого уровня: это диапазон 80000~80033.

Когда мы хотим найти 80032, мы можем найти его только по адресу, первый адрес которого равен 80000. Для непрерывного поиска 4 секторов требуется 4 операции ввода-вывода, чтобы получить

3+1+4=8

Поэтому добавление слоя в дерево B+ — худший вариант, в любом случае требуется всего 8 операций ввода-вывода, чтобы найти какие-либо данные.

Подводя итог: найдите 80 000 фрагментов данных (в худшем случае).

А. Без индекса, поиск по секторам, 80000/8 = 10000, без индекса требуется 10000 операций ввода-вывода

B. Индекс первого уровня, поскольку 80000-я запись находится в последнем секторе, 80000/1024 = 79, для индекса первого уровня требуется 79 операций ввода-вывода, используйте индекс первого уровня для поиска данных 4 раза ввода-вывода, индекс первого уровня. Требуется 83 операции ввода-вывода.

C. Вторичный индекс, поскольку 80 000-я запись находится в последнем секторе, 80000/32768 = 3, вторичный индекс требует 3 операций ввода-вывода, и требуется только 1 раз, чтобы использовать адрес интервала вторичного индекса для поиска первичного индексный ввод-вывод, то индексу первого уровня требуется 4 операции ввода-вывода для поиска данных, а индексу второго уровня требуется только 8 операций ввода-вывода для поиска данных.

Когда мы попадаем сюда, мы ясно чувствуем прелесть индекса, и даже ясно видим, как наше B+-дерево организует данные и индексы.

Если мы перевернем картинку выше на 90 градусов по часовой стрелке, то ясно увидим, что наше B+-дерево и есть эта модель.

Возможные вопросы по примерам в блоге:

А. Обязательно ли диапазон интервалов индексной таблицы равен 32?

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

б) Каждая запись в индексированной таблице занимает 16 байт?

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

в) Действительно ли требуется 100 операций ввода-вывода, если нет индексов для 800 записей?

Нет, в зависимости от размера страницы, прочитанной за один раз, чтение MySql по умолчанию составляет 16 КБ: 16 КБ / 64 = 250 записей, общий ввод-вывод запроса составляет не менее 250 записей,

По принципу локальности компьютера, когда используются данные сектора, данные вокруг него, скорее всего, использовались недавно, поэтому механизм кеша mysql будет поддерживать запрос на возврат 4-х страниц, то есть с текущей страницы запроса Начать двигать главу до размера 4 страницы, 4*16=64кб

То есть 64kb / 64 = 100 записей.За один ввод-вывод в кеш возвращается 100 записей, а затем как делать запросы — это знания, которые должен понимать движок InnoDB.

 3. Формирование структуры хранения индекса дерева B+ в MySql

Теперь я упрощаю эту картинку, а затем поворачиваю ее на 90 градусов, давайте посмотрим, как она выглядит.

Это относительно полное B+-дерево.Мы можем найти характеристики B+-дерева, если присмотримся повнимательнее.

А. Интервал индекса непрерывно сокращается от корневого узла, а сектор, в котором находятся данные описания, становится все более и более уточненным.

Б. Корневой узел хранит все индексы, и только дочерние узлы на нижнем уровне являются данными

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

Теперь дерево B+, описанное на картинке, на самом деле большая часть дерева B может это сделать, давайте посмотрим на разницу между деревом B и деревом B+

Разница между B-деревом и B+ деревом (основное отличие)

Отличие 1:

B-дерево также имеет данные в корневом узле, а затем данные, хранящиеся в корневом узле, являются индексом и данными.

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

Можно сказать, что родительский узел может иметь как индексы, так и данные, именно так хранятся B-деревья.

Корневой узел дерева B+ не имеет данных и хранит только индекс

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

Подведем итог:

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

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

Я чувствую, что иногда дерево B быстрее, чем дерево B+.Почему MySql использует дерево B+?

Поскольку запрос дерева B+ более стабилен, чем запрос дерева B, разработчикам и администраторам баз данных полезно выполнять на нем тесты производительности, а данные обнаружения журнала во время выполнения также будут очень точными.

Чтобы привести простой пример, возьмите две приведенные выше картинки: мы хотим запросить 7-е данные и 8-е данные, эти две записи находятся рядом друг с другом.

Используйте запрос B-дерева:

Седьмая запись: 1 ввод/вывод

Восьмая запись: 2 I/O

Используйте запрос дерева B+:

Седьмая запись: 2 I/O

Восьмая запись: 2 I/O

Мы видим, что для первого запроса с использованием B-дерева требуется 1 ввод-вывод, для второго требуется 2 ввода-вывода, а для B+-дерева требуется два ввода-вывода.

Это очевидно, видно, что эффективность запросов B-дерева очень нестабильна, особенно при увеличении количества слоев и увеличении интервала данных.

Отличие 2:

Эта разница уникальна для деревьев B+,

В B-дереве подузлы и подузлы изолированы друг от друга.Теперь мы создадим ситуацию, когда нам нужно запросить две записи в операторе запроса в B-дереве.

Например id = 6 и id = 8

Так как это оператор запроса, то что будет, если мы выполним его вместе, наша голова сначала переместится в корневую ноду для позиционирования, затем мы можем проверить запись с id=6, а затем перейти в корневую ноду для проверки индекса снова, и тогда голова будет позиционирована на id = 8 для этой записи

Очевидно, что наш запрос B-дерева выполняет позиционирование головок дважды.Мы знаем, что при чтении и записи дисков самые большие накладные расходы связаны с позиционированием головок, поэтому нам нужно выполнять позиционирование головок как можно реже.

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

 С помощью этого хвостового указателя мы используем дерево B+ для поиска записей с id = 6 и id = 8. Когда мы находим запись с id = 6 после позиционирования головы, она будет напрямую читать запись с id = 8 в соответствии с хвостовой указатель, для ускорения чтения и записи соседних секторов или нескольких смежных секторов

4. Резюме

Все приведенные выше описания являются просто обычным методом хранения данных дерева B +.На самом деле текущее хранилище MySql намного сложнее, чем у дерева B +, потому что наши соответствующие устройства или более поздние параметры по умолчанию для физического хранилища отличаются.

Приведет к другому хранилищу дерева B+

Требуется реальное трудоустройство или дальнейшее обучение, а до понимания MySql еще далеко

Supongo que te gusta

Origin blog.csdn.net/xxxzzzqqq_/article/details/130677352
Recomendado
Clasificación