Как работает переполнение страницы столбцами (InnoDB) в MySQL?

#mysql #sql #database #data-structures #mariadb

#mysql #sql #База данных #структуры данных #mariadb

Вопрос:

В документации говорится: «Хранятся ли столбцы вне страницы, зависит от размера страницы и общего размера строки».

1.- Это означает, что если у меня размер страницы 16 КБ, максимальный размер строки будет 8 КБ, следовательно, если у меня 4 столбца, будет ли максимальный размер каждого столбца 2 КБ (приблизительно)?

2.- Когда в документации говорится: «Хранятся ли столбцы вне страницы, зависит от размера страницы и общего размера строки.», это справедливо только для формата ДИНАМИЧЕСКИХ и СЖАТЫХ столбцов, или это также для формата ИЗБЫТОЧНЫХ и КОМПАКТНЫХ столбцов, или когда ИЗБЫТОЧНЫЕ и КОМПАКТНЫЕиспользуются ВСЕГДА так, чтобы избыточные данные столбца отправлялись на страницу переполнения, максимальный размер строки — 768 байт? Разве это не занимает свободное пространство остальной части строки ?.

3. — Размер индексов зависит от размера строки и столбцов, то есть, возвращаясь к тому, что я задал в вопросе 1, каждая строка будет составлять 2 КБ (приблизительно), и если она имеет тип ДИНАМИЧЕСКОГО формата столбца, максимальный размер индекса будет 2 КБ(приблизительно 2000 байт), а не 3072 байта, верно?

Комментарии:

1. 3. размер индексов фиксирован на уровне 3076 байт в поддерживаемых версиях MariaDB размер innodb (innodb_large_prefix по умолчанию ON долгое время). Или меньше для страниц меньшего размера. Это происходит независимо от наличия / отсутствия хранилища страниц или формата столбца). Вторичные индексы (не первичный ключ) не хранятся в строке.

2. Я нашел ответ на вопрос 3 (я должен был прочитать немного больше xd), В документации говорится: «Если вы уменьшите размер страницы InnoDB до 8 КБ или 4 КБ, указав параметр innodb_page_size при создании экземпляра MySQL, максимальная длина индексного ключа пропорционально уменьшается в зависимости от предела 3072 байта для страницы размером 16 КБ. То есть максимальная длина индексного ключа составляет 1536 байт при размере страницы 8 КБ и 768 байт при размере страницы 4 КБ «.

3. Некоторые из них я обновил, прежде чем ответить вам. Надеюсь, теперь все ясно. Вы хотите получить ответы на вопросы 1 и 2?

4. да, я хочу получить ответы на вопросы 1 и 2 🙂

Ответ №1:

Забудьте о 2 КБ в вашем примере; это вводит в заблуждение и в основном не имеет значения.

Да, существует ограничение примерно на 8 КБ на то, что помещается в блок данных размером 16 КБ. (Индексные блоки рассматриваются позже.)

Столбцы либо переходят в хранилище размером до 8 КБ, либо в другой блок (хранилище «вне записи»).

MySQL решает, помещать ли столбец в это ограничение в 8 КБ на основе

  • Тип данных — числовые столбцы всегда входят; строки и большие двоичные объекты зависят.
  • Формат строки и размер столбца — небольшие строки и большие двоичные объекты могут быть встроены или могут быть недоступны для записи. Конечно, любой текст / большой двоичный объект размером более 8 КБ должен был бы остаться незарегистрированным.

Давайте рассмотрим другой пример: 4 столбца по 3 КБ каждый и 4 «маленькие» строки. Сначала 4 маленьким струнам будет разрешено записаться. Тогда, я думаю, двум из них будет назначено быть записанными, но последние два не подойдут, так что…

  • Для COMPACT первые 768 байт будут записаны, остальные будут не записаны.
  • Для DYNAMIC ни один из столбцов не записан.
  • Текст короче 40 байт «всегда» хранится в записи.

(СЖАТЫЙ добавляет еще одну проблему — сжатый блок меньше 16 КБ.)

Для текста / большого двоичного объекта, который должен быть удален из записи, 20-байтовый «указатель» остается в записи, чтобы его можно было найти. Это фактически говорит о том, что у вас не может быть более 400 (8K / 20) больших текстовых столбцов (не 1017, упомянутых ниже).

Индексы хранятся в отдельном BTree. Он действует очень похоже на Data BTree. Однако с ограничением 3072 (на столбец в индексе) нет понятия «вне записи». (Примечание: это 3072 байта, что соответствует НАБОРУ СИМВОЛОВ `VARCHAR(768) utf8mb4. 768 — это _characters .) Максимальная длина ключа составляет 3500 байт.

Вернемся к одному из ваших первых пунктов… Максимальный размер строки составляет (я думаю) 4 ГБ. 8 КБ — это всего лишь то, что может храниться в его записываемой части. Дополнительные «ограничения»: http://mysql.rjweb.org/doc.php/limits

Что поражает некоторых людей, так это «слишком много колонок». Предел в InnoDB равен 1017, что близко к соответствию пределу в 8 КБ, если все 1017 равны BIGINTs . Но с большим DECIMALs или средним размером VARCHARs вы можете создать строку с менее чем 1017 столбцами, которые не поместятся, независимо от формата строки.

Возвращаясь к вашему вопросу 1. Нет. Каждый из ваших 4 текстовых столбцов может составлять много мегабайт.

Вопрос 2 намного сложнее. Я ответил на некоторые из них выше.

«Свободное пространство» — в InnoDB BTrees много невостребованного свободного места. Настолько, что у меня есть эмпирическое правило, Которое гласит, что простое вычисление размера строки (4 байта на INT и т. Д.) Необходимо умножить на от 2 до 3, Чтобы учесть все накладные расходы и «свободное» пространство. Да, часть этого «свободного пространства» время от времени освобождается. Но детали длинные и сложные.

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

Извините, но это только упрощенная версия того, что происходит.