Spec-Zone.ru › MySQL 8.4

17.10 Форматы строк InnoDB

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

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

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

Движок хранения InnoDB поддерживает четыре формата строк: REDUNDANT, COMPACT, DYNAMIC и COMPRESSED.

Таблица 17.14 Обзор форматов строк InnoDB

Таблица 17.14 Обзор форматов строк InnoDB
Формат строки Характеристики компактного хранения Улучшенное хранение столбцов переменной длины Поддержка префикса ключа индекса большой длины Поддержка сжатия Поддерживаемые типы табличных пространств
REDUNDANT Нет Нет Нет Нет system, file-per-table, general
COMPACT Да Нет Нет Нет system, file-per-table, general
DYNAMIC Да Да Да Нет system, file-per-table, general
COMPRESSED Да Да Да Да file-per-table, general

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

  • Формат строки REDUNDANT

  • Формат строки COMPACT

  • Формат строки DYNAMIC

  • Формат строки COMPRESSED

  • Определение формата строки таблицы

  • Определение формата строки таблицы

Формат строки REDUNDANT

Формат REDUNDANT обеспечивает совместимость со старыми версиями MySQL.

Таблицы, использующие формат строки REDUNDANT, хранят первые 768 байт значений столбцов переменной длины (VARCHAR, VARBINARY и BLOB и TEXT типы) в записи индекса в узле B-дерева, а остальная часть хранится на страницах переполнения. Столбцы фиксированной длины, превышающие или равные 768 байтам, кодируются как столбцы переменной длины, которые могут храниться вне страницы. Например, столбец CHAR(255) может превышать 768 байт, если максимальная длина байта набора символов больше 3, как это происходит в utf8mb4.

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

Характеристики хранения формата строк REDUNDANT

Формат строки REDUNDANT имеет следующие характеристики хранения:

  • Каждая запись индекса содержит заголовок длиной 6 байт. Заголовок используется для связывания последовательных записей и для блокировки на уровне строки.

  • Записи в кластеризованном индексе содержат поля для всех определённых пользователем столбцов. Кроме того, есть поле идентификатора транзакции длиной 6 байт и поле указателя отката длиной 7 байт.

  • Если для таблицы не определён первичный ключ, каждая запись кластеризованного индекса также содержит поле идентификатора строки длиной 6 байт.

  • Каждая запись вторичного индекса содержит все столбцы первичного ключа, определённые для ключа кластеризованного индекса, которые не входят во вторичный индекс.

  • Запись содержит указатель на каждое поле записи. Если общая длина полей в записи меньше 128 байт, указатель занимает один байт; в противном случае — два байта. Массив указателей называется каталогом записи. Область, на которую указывают указатели, — это данные записи.

  • Внутренне столбцы символов фиксированной длины, такие как CHAR(10), хранятся в формате фиксированной длины. Прицепные пробелы не обрезаются из столбцов VARCHAR.

  • Столбцы фиксированной длины, превышающие или равные 768 байтам, кодируются как столбцы переменной длины, которые могут храниться вне страницы. Например, столбец CHAR(255) может превышать 768 байт, если максимальная длина байта набора символов больше 3, как это происходит в utf8mb4.

  • Значение SQL NULL зарезервирует один или два байта в каталоге записи. Значение SQL NULL зарезервирует ноль байтов в части данных записи, если оно хранится в столбце переменной длины. Для столбца фиксированной длины фиксированная длина столбца зарезервируется в части данных записи. Резервирование фиксированного пространства для значений NULL позволяет обновлять столбцы на месте от значений NULL до не-NULL значений без фрагментации страниц индекса.

Формат строк COMPACT

Формат строк COMPACT уменьшает объем занимаемой памяти на 20% по сравнению с форматом строк REDUNDANT, но при этом увеличивает использование ЦП для некоторых операций. Если ваша рабочая нагрузка — типичная и ограничена скоростью кэша и скоростью диска, то формат COMPACT, скорее всего, будет быстрее. Если же рабочая нагрузка ограничена скоростью ЦП, компактный формат может быть медленнее.

Таблицы, использующие формат строк COMPACT, хранят первые 768 байт значений столбцов переменной длины (VARCHAR, VARBINARY и BLOB и TEXT типы) в записях индекса внутри узла, а оставшуюся часть — на страницах переполнения. Столбцы фиксированной длины, превышающие или равные 768 байтам, кодируются как столбцы переменной длины, которые могут храниться вне страницы. Например, столбец CHAR(255) может превышать 768 байт, если максимальная длина байта набора символов больше 3, как это происходит в utf8mb4.

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

Характеристики хранения формата строк COMPACT

Формат строк COMPACT имеет следующие характеристики хранения:

  • Каждая запись индекса содержит 5-байтовый заголовок, который может предваряться заголовком переменной длины. Заголовок используется для связывания последовательных записей и для блокировки на уровне строк.

  • Переменная часть заголовка записи содержит битовый вектор для указания столбцов NULL. Если число столбцов в индексе, которые можно NULL, равно N, битовый вектор занимает CEILING(N/8) байта. (Например, если есть от 9 до 16 столбцов, которые можно NULL, битовый вектор занимает два байта.) Столбцы, которые NULL, не занимают места, кроме бита в этом векторе. Переменная часть заголовка также содержит длины столбцов переменной длины. Длина каждого значения занимает один или два байта, в зависимости от максимальной длины столбца. Если все столбцы в индексе NOT NULL и имеют фиксированную длину, заголовок записи не имеет переменной части.

  • Для каждого столбца переменной длины, отличного от NULL, заголовок записи содержит длину столбца в один или два байта. Два байта нужны только в том случае, если часть столбца хранится во внешних страницах переполнения или максимальная длина превышает 255 байт, а фактическая длина превышает 127 байт. Для внешнего столбца 2-байтовая длина указывает длину внутренней части плюс 20-байтовый указатель на внешнюю часть. Внутренняя часть составляет 768 байт, поэтому длина составляет 768 + 20. 20-байтовый указатель хранит истинную длину столбца.

  • За заголовком записи следуют данные содержимого столбцов, отличных от NULL.

  • Записи в кластерном индексе содержат поля для всех столбцов, определённых пользователем. Кроме того, есть 6-байтовое поле идентификатора транзакции и 7-байтовое поле указателя хода.

  • Если для таблицы не определён первичный ключ, каждая запись кластерного индекса также содержит 6-байтовое поле идентификатора строки.

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

  • Внутренне, для наборов символов с фиксированной длиной, столбцы символов фиксированной длины, такие как CHAR(10), хранятся в формате фиксированной длины.

    Приводящие пробелы не обрезаются из столбцов VARCHAR.

  • Внутренне, для наборов символов с переменной длиной, таких как utf8mb3 и utf8mb4, InnoDB пытается сохранить CHAR(N) в N байтах, обрезая при этом прилегающие пробелы. Если длина в байтах значения столбца CHAR(N) превышает N байт, прилегающие пробелы обрезаются до максимального значения длины в байтах значения столбца. Максимальная длина столбца CHAR(N) составляет максимальную длину символа в байтах × N.

    Минимально N байта зарезервировано для CHAR(N). Резервирование минимального пространства N во многих случаях позволяет выполнять обновления столбцов на месте, не вызывая фрагментацию страниц индекса. По сравнению с этим, столбцы CHAR(N) занимают максимальную длину символа в байтах × N при использовании формата строк REDUNDANT.

    Столбцы фиксированной длины, превышающие или равные 768 байтам, кодируются как столбцы переменной длины, которые могут храниться вне страницы. Например, столбец CHAR(255) может превышать 768 байт, если максимальная длина байта набора символов больше 3, как это происходит в utf8mb4.

Формат строк DYNAMIC

Формат строк DYNAMIC предлагает те же характеристики хранения, что и формат строк COMPACT, но добавляет расширенные возможности хранения для длинных столбцов переменной длины и поддерживает большие префиксы ключей индекса.

При создании таблицы с форматом ROW_FORMAT=DYNAMIC, формат InnoDB может хранить значения длинных столбцов переменной длины (для VARCHAR, VARBINARY и BLOB и TEXT типов) полностью вне страницы, при этом запись кластерного индекса содержит только 20-байтовый указатель на страницу переполнения. Столбцы фиксированной длины, превышающие или равные 768 байтам, кодируются как столбцы переменной длины. Например, столбец CHAR(255) может превышать 768 байт, если максимальная длина байта набора символов больше 3, как это происходит в utf8mb4.

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

Формат строк DYNAMIC сохраняет эффективность хранения всей строки в узле индекса, если она помещается (как форматы COMPACT и REDUNDANT), но формат строк DYNAMIC избегает проблемы заполнения узлов B-дерева большим количеством байтов данных длинных столбцов. Формат строк DYNAMIC основан на идее о том, что если часть длинного значения данных хранится вне страницы, то наиболее эффективным является хранение всего значения вне страницы. С форматом DYNAMIC более короткие столбцы, скорее всего, останутся в узле B-дерева, сводя к минимуму количество страниц переполнения, необходимых для данной строки.

Формат строк DYNAMIC поддерживает префиксы ключей индекса до 3072 байт.

Таблицы, использующие формат строк DYNAMIC, могут храниться в системном табличном пространстве, табличных пространствах на файл на таблицу и в общих табличных пространствах. Чтобы хранить таблицы DYNAMIC в системном табличном пространстве, отключите innodb_file_per_table и используйте обычное оператор CREATE TABLE или ALTER TABLE, или используйте опцию таблицы TABLESPACE [=] innodb_system с CREATE TABLE или ALTER TABLE. Переменная innodb_file_per_table не применима к общим табличным пространствам, а также не применима при использовании опции таблицы TABLESPACE [=] innodb_system для хранения таблиц DYNAMIC в системном табличном пространстве.

Характеристики хранения формата строк DYNAMIC

Формат строк DYNAMIC является вариацией формата строк COMPACT. Для ознакомления с характеристиками хранения смотрите Характеристики хранения формата строк COMPACT.

Формат строк COMPRESSED

Формат строк COMPRESSED предлагает те же характеристики и возможности хранения, что и формат строк DYNAMIC, но добавляет поддержку сжатия данных таблицы и индексов.

Формат строк COMPRESSED использует аналогичные внутренние детали для хранения данных на страницах за пределами текущей страницы, что и формат строк DYNAMIC, с дополнительными соображениями по хранению и производительности из-за сжатия данных таблицы и индексов и использования более маленьких размеров страниц. В формате строк COMPRESSED параметр KEY_BLOCK_SIZE управляет тем, сколько данных столбцов хранится в индексе кластеризации, а сколько размещается на страницах сброса. Дополнительную информацию о формате строк COMPRESSED см. в разделе 17.9 «Сжатие таблиц и страниц InnoDB».

Формат строк COMPRESSED поддерживает префиксы ключей индекса длиной до 3072 байт.

Таблицы, использующие формат строк COMPRESSED, могут быть созданы в файловых таблицах или общих таблицах. Системный табличный пространство не поддерживает формат строк COMPRESSED. Для хранения таблицы COMPRESSED в файловом табличном пространстве необходимо включить переменную innodb_file_per_table. Переменная innodb_file_per_table не применяется к общим таблицам. Общие табличные пространства поддерживают все форматы строк с оговоркой, что сжатые и несжатые таблицы не могут сосуществовать в одном общем табличном пространстве из-за различий в размерах физических страниц. Дополнительную информацию см. в разделе 17.6.3.3 «Общие табличные пространства».

Характеристики хранения сжатого формата строк

Формат строк COMPRESSED является вариантом формата строк COMPACT. Характеристики хранения см. в характеристиках хранения формата строк COMPACT.

Определение формата строк таблицы

По умолчанию формат строк для таблиц InnoDB определяется переменной innodb_default_row_format, которая имеет значение по умолчанию DYNAMIC. Формат строк по умолчанию используется, когда опция таблицы ROW_FORMAT не определена явно или когда задано значение ROW_FORMAT=DEFAULT.

Формат строк таблицы можно явно определить, используя опцию таблицы ROW_FORMAT в инструкции CREATE TABLE или ALTER TABLE. Например:

CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;

Явно заданное значение ROW_FORMAT переопределяет формат строк по умолчанию. Указание ROW_FORMAT=DEFAULT эквивалентно использованию неявного значения по умолчанию.

Переменную innodb_default_row_format можно изменить динамически:

mysql> SET GLOBAL innodb_default_row_format=DYNAMIC;

Допустимые значения для innodb_default_row_format включают DYNAMIC, COMPACT и REDUNDANT. Формат строк COMPRESSED, который не поддерживается для использования в системном табличном пространстве, не может быть определен как значение по умолчанию. Он может быть указан только явно в инструкции CREATE TABLE или ALTER TABLE. Попытка установить переменную innodb_default_row_format в значение COMPRESSED приведет к ошибке:

mysql> SET GLOBAL innodb_default_row_format=COMPRESSED;
ERROR 1231 (42000): Variable 'innodb_default_row_format'
can't be set to the value of 'COMPRESSED'

Новосозданные таблицы используют формат строк, определенный переменной innodb_default_row_format, когда опция ROW_FORMAT не задана явно или используется значение ROW_FORMAT=DEFAULT. Например, следующие инструкции CREATE TABLE используют формат строк, определенный переменной innodb_default_row_format.

CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c1 INT) ROW_FORMAT=DEFAULT;

Если опция ROW_FORMAT не задана явно или используется ROW_FORMAT=DEFAULT, операция по перестроению таблицы незаметно изменяет формат строк таблицы на формат, определенный переменной innodb_default_row_format.

Операции перестроения таблицы включают операции ALTER TABLE, использующие ALGORITHM=COPY или ALGORITHM=INPLACE, где требуется перестроение таблицы. Дополнительную информацию см. в разделе 17.12.1 «Операции DDL в режиме онлайн». OPTIMIZE TABLE также является операцией перестроения таблицы.

Следующий пример демонстрирует операцию перестроения таблицы, которая незаметно изменяет формат строк таблицы, созданной без явного определения формата строк.

mysql> SELECT @@innodb_default_row_format;
+-----------------------------+
| @@innodb_default_row_format |
+-----------------------------+
| dynamic                     |
+-----------------------------+

mysql> CREATE TABLE t1 (c1 INT);

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ***************************
     TABLE_ID: 54
         NAME: test/t1
         FLAG: 33
       N_COLS: 4
        SPACE: 35
   ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single

mysql> SET GLOBAL innodb_default_row_format=COMPACT;

mysql> ALTER TABLE t1 ADD COLUMN (c2 INT);

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ***************************
     TABLE_ID: 55
         NAME: test/t1
         FLAG: 1
       N_COLS: 5
        SPACE: 36
   ROW_FORMAT: Compact
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single

Перед изменением формата строк существующих таблиц с форматов REDUNDANT или COMPACT на DYNAMIC рассмотрите возможные проблемы.

  • Форматы строк REDUNDANT и COMPACT поддерживают максимальную длину префикса ключа индекса 767 байт, в то время как форматы строк DYNAMIC и COMPRESSED поддерживают длину префикса ключа индекса 3072 байт. В среде репликации, если переменная innodb_default_row_format установлена в DYNAMIC на источнике и в COMPACT на реплике, следующая инструкция DDL, которая не определяет явно формат строк, выполняется успешно на источнике, но не на реплике:

    CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 VARCHAR(5000), KEY i1(c2(3070)));
    

    Дополнительная информация представлена в разделе 17.21 «Ограничения InnoDB».

  • Импорт таблицы, которая не определяет явно формат строк, приводит к ошибке несоответствия схемы, если значение innodb_default_row_format на сервере-источнике отличается от значения на сервере-приемнике. Дополнительную информацию см. в разделе 17.6.1.3 «Импорт таблиц InnoDB».

Определение формата строк таблицы

Для определения формата строк таблицы используйте SHOW TABLE STATUS:

mysql> SHOW TABLE STATUS IN test1\G
*************************** 1. row ***************************
           Name: t1
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 16384
      Data_free: 0
 Auto_increment: 1
    Create_time: 2016-09-14 16:29:38
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb4_0900_ai_ci
       Checksum: NULL
 Create_options:
        Comment:

В качестве альтернативы можно запросить таблицу схемы информации INNODB_TABLES:

mysql> SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME='test1/t1';
+----------+------------+
| NAME     | ROW_FORMAT |
+----------+------------+
| test1/t1 | Dynamic    |
+----------+------------+

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/innodb-row-format.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API