17.10 Форматы строк InnoDB
Формат строки таблицы определяет, как её строки хранятся физически, что, в свою очередь, может влиять на производительность запросов и операций DML. Чем больше строк помещается на одной странице диска, тем быстрее работают запросы и поиск по индексу, меньше требуется оперативной памяти в буферном пуле и меньше операций ввода-вывода требуется для записи обновлённых значений.
Данные в каждой таблице разделены на страницы. Страницы, составляющие каждую таблицу, упорядочены в структуре данных типа дерево, называемой индексом B-дерева. Данные таблицы и вторичные индексы используют такую структуру. Индекс B-дерева, представляющий всю таблицу, называется кластеризованным индексом, который организован в соответствии со столбцами первичного ключа. Узлы структуры данных кластеризованного индекса содержат значения всех столбцов в строке. Узлы структуры данных вторичного индекса содержат значения столбцов индекса и столбцов первичного ключа.
Столбцы переменной длины являются исключением из правила, что значения столбцов хранятся в узлах индекса B-дерева. Столбцы переменной длины, которые слишком длинные для размещения на странице индекса B-дерева, хранятся на отдельных страницах диска, называемых страницами переполнения. Такие столбцы называются столбцами вне страницы. Значения столбцов вне страницы хранятся в списках, связанных по отдельности, страницами переполнения, при этом каждый такой столбец имеет свой собственный список из одной или нескольких страниц переполнения. В зависимости от длины столбца все или префикс значений столбца переменной длины хранятся в B-дереве, чтобы избежать потерь места и необходимости чтения отдельной страницы.
Движок хранения InnoDB поддерживает четыре формата строк: REDUNDANT, COMPACT, DYNAMIC и COMPRESSED.
Таблица 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
Формат 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зарезервирует один или два байта в каталоге записи. Значение SQLNULLзарезервирует ноль байтов в части данных записи, если оно хранится в столбце переменной длины. Для столбца фиксированной длины фиксированная длина столбца зарезервируется в части данных записи. Резервирование фиксированного пространства для значений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(байта. (Например, если есть от 9 до 16 столбцов, которые можноN/8)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 Table and Page Compression».
Формат строк COMPRESSED поддерживает префиксы ключей индексов длиной до 3072 байт.
Таблицы, использующие формат строк COMPRESSED, могут быть созданы в файловых табличных пространствах или общих табличных пространствах. Система табличного пространства не поддерживает формат строк COMPRESSED. Для хранения таблицы COMPRESSED в файловом табличном пространстве необходимо включить переменную innodb_file_per_table. Переменная innodb_file_per_table не применима к общим табличным пространствам. Общие табличные пространства поддерживают все форматы строк с оговоркой, что сжатые и несжатые таблицы не могут сосуществовать в одном общем табличном пространстве из-за различий в размерах физических страниц. Для получения дополнительной информации см. Раздел 17.6.3.3, «Общие табличные пространства».
Характеристики хранения формата строк COMPRESSED
Формат строк 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, «Online DDL Operations». Операция 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.