Простое удаление, я нашел так много знаний...

Java MySQL
Простое удаление, я нашел так много знаний...

Эта статья участвовала в "Проект «Звезда раскопок»”, чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.

Удалить на самом деле не удалить

Студенты, знакомые с механизмом хранения mysql innodb, должны знать, что когда мы выполняем удаление, данные на самом деле не удаляются, а удаляется только идентификатор удаления соответствующих данных.deleteMarkОн включен, так что каждый раз, когда выполняется запрос, если обнаруживается, что данные существуют, но включена функция удаления, он все равно будет возвращаться пустым. Из-за этой детали феномен «Я явно удалил данные, почему место не освобождается" часто встречается.

15M  7  6 18:46 user_info.ibd #删除前
15M 10  4 16:47 user_info.ibd #删除后

Почему бы не удалить его, а отметить?

Мы знаем, что механизм хранения InnoDB поддерживает MVCC, то есть управление несколькими версиями.Благодаря MVCC mysql не нужно блокировать при запросе данных в транзакции, что может обеспечить хороший параллелизм и обеспечить повторяемость чтений.Это очень важная характеристика . Так как же он туда попал? Ответ — журнал отмен, который можно просто понимать как запись данных перед обновлением в журнал отмен каждый раз, когда данные обновляются, так что, когда требуется откат, необходимо только следить за журналом отмен, чтобы найти историческую данные. Журнал отмен и исходные данные связаны указателями, то есть каждый фрагмент данных имеет указатель отката, указывающий на журнал отмен.

Если InnoDB действительно стирает данные с диска при удалении данных, то в этот раз:

  1. Другие транзакции не могут найти исходные данные через журнал отмены.
  2. Повторяемое чтение этой функции будет нарушено

Не будет ли пустой тратой места просто отметить

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

image.png

постраничное хранилище

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

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

image.png

строка и страница: Что нам нужно знать, так это то, что мы, наконец, получили через дерево B+Не данные нашей целевой строки, а страница, на которой расположены данные целевой строки., на этой странице много данных, все они соседствуют с порядковым номером.Когда целевая страница будет найдена, целевая страница будет загружена в память, а затем методом дихотомии будут найдены целевые данные. Вы можете спросить, стоимость поиска это не только дисковый ввод-вывод, но и накладные расходы на бинарный поиск. Здесь это бесспорно, но мы вообще игнорируем эту часть накладных расходов, потому что скорость выборки процессора в памяти очень высокая, а страница всего 16k, а данных немного.

Количество IO не обязательно равно высоте дерева: Ранее мы говорили, что высота дерева равна количеству операций ввода-вывода, что не очень точно. Мы знаем, что корневой узел дерева должен находиться в памяти, поэтому для фрагмента данных высотой 3, нужно всего 2 IO.Это собственно и понятно.Ведь корневая нода занимает всего одну страницу места, а одна страница всего 16К, чего по памяти более чем достаточно. Но иногда в памяти можно разместить и второй слой дерева. Предположим теперь, что первичный ключ — это bigint. Мы знаем, что bigint занимает 8 байт. Для индекса, кроме места, занимаемого самим типом, есть еще указатель, этот указатель занимает 6 байт, то для корневого узла он может хранить около 16K/(8+6)B = 1170 данных, каждое данные может указывать на страницу (то есть на ее следующий слой), так что все дерево Второй слой занимает примерно 1170*16К = 18М пространства, что не так уж и много.Для памяти машины это почти капля в море, поэтому второй слой часто тоже в памяти, так что он попадает в дерево B+.Затраты на ввод-вывод при извлечении данных должны быть ниже теоретических.

Из вышеизложенного мы знаем, что на скорость извлечения фрагмента данных в основном влияет высота дерева. Это не имеет никакого отношения к размеру вашей таблицы данных. В действительности некоторые люди могут рассматривать подтаблицы, когда данные выражаются на уровне миллионов. Лично я считаю, что это немного недооценивает возможности дерева B+. Возьмем в качестве примера первичный ключевой индекс типа bigint.Если предположить, что строка данных занимает 1 КБ (что теоретически достаточно много), то одна страница может хранить16K/1K=16фрагментов данных, для дерева B+ высотой 3 он может хранить1170*1170*16=21902400данных, почти 20 млн. Если ваши строки данных занимают меньше места, вы можете хранить больше данных, поэтому не так разумно просто судить о том, нужно ли вам разбивать таблицы на основе количества строк данных.

Что делать, если многоразовое пространство не было использовано?

Ранее мы упоминали о том, что удаленные данные не будут удалены, а только помечены логотипом deleteMark, а затем будут повторно использованы, но если они не были повторно использованы, то место не будет потрачено зря, а еще хуже, если Многие удаленные пространства данных не используются повторно, что приведет к сильной фрагментации пространства страницы.Чтобы решить эту ситуацию, в MySQL существует функция, называемая слиянием страниц.Что это значит? Простое понимание состоит в том, что на странице А теперь много места, которое можно повторно использовать, и на соседней странице Б также много места, которое можно повторно использовать. В это время страница А может быть объединена со страницей Б. Если страница могут быть сохранены после слияния, так много страницы, которая выходит, может быть использована в следующий раз, чтобы добиться эффекта максимального использования страницы.

image.png

Ключ к слиянию требует, чтобы предыдущая или следующая страница текущей страницы также имела большое количество фрагментированного пространства, зачем здесь это нужно?многоЭто очень важно. Действие слияния можно просто понимать как перемещение данных других страниц. Если обе страницы pageA и pageB имеют лишь небольшое количество повторно используемого пространства, то после слияния, даже если страница A может быть заполнена, другая страница Страница Все еще есть место для фрагментации, и фрагментация больше.В это время накладные расходы на перемещение данных могут быть больше, чем накладные расходы на хранение, что не стоит потери.

image.png

И будет серьезная проблема, страница B может быть объединена со страницей C, тогда фрагментация страницы C больше... Это кажется бездонной ямой, из-за которой многие страницы перемещают данные. Следовательно, разумное условие слияния имеет решающее значение.MERGE_THRESHOLDЭтот параметр влияет.Его значение по умолчанию 50%.Намерение 50% очевидно.Две 50% могут спасти страницу.

image.pngВозьмем пример. 50% данных страницы А было удалено, а соседняя страница Б использует только менее 50% данных. В это время данные страницы Б будут перемещены на страницу А, тогда вся страница Б будет пустая страница. Ее можно использовать для других данных. Что вам нужно знать, так это то, что в дополнение к удалениям, вызывающим слияние страниц, обновления также могут вызывать слияние страниц.

Слияния и разделения

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

image.pngВозьмем приведенный выше рисунок в качестве примера, когда мы хотим вставить 5 фрагментов данных, мы должны попытаться поместить их на страницу A, но на странице A в настоящее время недостаточно места для хранения фрагмента данных, поэтому мы пытаемся найти соседнюю страницу. страница B страницы A, но, к сожалению, в это время Единственное, что страница B не имеет достаточно места для хранения части данных.Из-за непрерывности данных данные 5 должны быть между данными 4 и данными 6, тогда только новая страница может быть создана. После создания новой страницы она попытается переместить часть со страницы А. Данные помещаются на новую страницу, и отношения между страницами будут реорганизованы, то есть новая страница страница С будет разделена между страницей А и страница Б.

image.pngРазделение страниц уменьшит использование страниц. Существует много причин для разделения страниц, например:

  1. Например, дискретная вставка, приводящая к прерывистым данным.
  2. Обновите запись до записи большего размера, что приведет к нехватке места

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

Вручную перестроить таблицу

Слияние и разбиение страниц в основном происходит при вставке, удалении или обновлении и бывает при соблюдении определенных условий. Если эти условия не выполняются все время, то фрагменты не могут быть очищены, что часто происходит в это время"У меня на дисплее видно, что данных не так много, почему они до сих пор занимают столько места«Это явление, в ответ на это явление, некоторые люди говорят, что нужно перестроить индекс, это правда, перестроение индекса может сделать данные более компактными, а коэффициент использования страницы выше. Но как перестроить индекс? Вы можете подумать о первыйdrop indexпотомadd index, это кажется не столь точным.

  • Если индекс, который нужно перестроить, является обычным индексом, хорошо использовать этот метод.Следует отметить, что если ваш бизнес TPS большой, рекомендуется выполнять его в период низкой пиковой активности, потому что, хотя mysql поддерживает онлайн ddl, процесс перестроения индекса по-прежнему очень сложен, потребляет ресурсы процессора и ввода-вывода.
  • Если вы хотите перестроить индекс первичного ключа, то возникает проблема Прежде всего, если ваш индекс первичного ключа настроен на автоматический рост, удаление не поддерживается. Во-вторых, если ваш первичный ключ не настроен на самовозрастание, прямое удаление — это не то, что мы себе представляли.Мы знаем, что обычные индексы будут записывать значение первичного ключа в дополнение к индексному полю самой записи. чтобы удалить индекс напрямую, то через обычный индекс соответствующая запись строки не будет найдена, поэтому InnoDB требует индекса первичного ключа. В это время InnoDB попытается найти уникальный индекс в таблице в качестве первичного ключа. Если есть не является уникальным индексом, он автоматически создаст индекс строки по умолчанию для первичного ключа, после того, как новый индекс первичного ключа будет установлен, необходимо изменить связанный обычный индекс для хранения нового первичного ключа, но если он изменен таким образом, затраты будут очень большими, особенно при наличии большого количества обычных индексов, поэтому InnoDB просто решит перестроить таблицу. Для следующей операции добавления индекса индекс первичного ключа также будет изменен, поэтому он также решит перестроить таблицу, и, наконец, можно обнаружить, что удаление и добавление индекса первичного ключа фактически делают то же самое.

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

alter table xx engine=InnoDB

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

  1. Сканировать все записи в индексе первичного ключа исходной таблицы
  2. Создать новые записи дерева b+ во временный файл
  3. В процессе формирования временных файлов новые изменения записываются в журнал строк журнала переноса.
  4. После создания временного файла примените изменения во время журнала строк к новому временному файлу.
  5. Затем замените временный файл текущим файлом

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

Перестройка таблицы не обязательно уменьшает пространство

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

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

  1. Если ваш стол сам по себе компактный, потому резервирование 1/16 станет больше.
  2. После перестроения таблицы в первый раз часть зарезервированного места израсходована за счет новых вставок (здесь следует отметить, что зарезервированное место не израсходовано, часть еще осталась), но новые страницы не используется, поэтому общее пространство не изменилось.В это время, если таблица будет перестроена снова, 1/16 таблицы будет зарезервирована, что приведет к применению новых страниц, и пространство станет больше.

Наконец, поиск в WeChat [притворитесь, что понимаете программирование], если у вас есть какие-либо вопросы, пожалуйста, свяжитесь со мной, если есть проблема с моей статьей, вы можете исправить меня, если вам нравится учиться, нравится учиться, вы можете следить меня.