Ошибка создания таблицы InnoDB: «слишком большой размер строки»

11

У нас есть несколько инженеров, которые объединяют нормализованную структуру БД во временную таблицу для создания отчета. Столбцы указаны как TEXT NOT NULL(я знаю, «почему они это делают?»; Давайте просто предположим, что мы обращаемся к этому).

Мы используем MySQL 5.1.48 Community RHEL5 с плагином InnoDB 1.0.9 в Linux.

При использовании MyISAM мы никогда не сталкивались с предельными размерами таблицы максимальными столбцами или максимальной длиной строки (во время исследования мы достигли максимального значения столбцов 2598 (2599th вызывает ошибку 1117). С InnoDB мы достигаем пределов. Эти ограничения проявляются при создании таблица (без вставки данных) как:

ОШИБКА 1118 (42000) в строке 1: слишком большой размер строки. Максимальный размер строки для используемого типа таблицы, не считая больших двоичных объектов, составляет 8126. Некоторые столбцы необходимо изменить на TEXT или BLOB.

Я ищу ответы на следующие вопросы:

  1. Какова детальная формула для определения размера строки при использовании партий столбцов v / v / b / t? Я пробовал несколько различных формул, используя varchar(N)столбцы (где N находится между 1 и 512), кодировку UTF8 (* 3) и столько столбцов, сколько таблица займет до сбоя. Ни одна из комбинаций, которые я пробовал, не дает значений, которые соответствуют реальным результатам теста.

  2. Какие еще «накладные расходы» следует учитывать при расчете размера строки?

  3. Почему сообщение об ошибке меняется с 8126 на 65535 при переходе от создания таблиц со столбцами varchar (109) к столбцам varchar (110)?


источник
У меня такая же проблема. Когда я проверял базу данных, я обнаружил, что одна из надстроек в веб-браузер вставляла HTML-код в исходный код страницы (даже в форму), и это вызывало проблему.
HTML не злодей. Ни размер этого HTML. У вас должно быть несколько столбцов text / varchar и вы столкнулись с некоторыми ограничениями, которые можно обойти.
Рик Джеймс

Ответы:

19

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

Центральный файл табличного пространства (ibdata1) всегда имеет формат антилопы . Если вы используете файл для каждой таблицы, вы можете настроить отдельные файлы в формате Barracuda , установив innodb_file_format=Barracudaв my.cnf.

Основные моменты:

  • Одна страница размером 16 КБ данных InnoDB должна содержать как минимум две строки данных. Кроме того, каждая страница имеет верхний и нижний колонтитулы, содержащие контрольные суммы страниц и порядковый номер журнала и так далее. Вот где вы получите свой предел чуть менее 8 КБ на строку.

  • Типы данных фиксированного размера, такие как INTEGER, DATE, FLOAT, CHAR, хранятся на этой первичной странице данных и учитываются при ограничении размера строки.

  • Типы данных переменного размера, такие как VARCHAR, TEXT, BLOB, хранятся на страницах переполнения, поэтому они не учитываются полностью до предела размера строки. В антилопе до 768 байт таких столбцов хранятся на первичной странице данных в дополнение к хранению на странице переполнения. Barracuda поддерживает динамический формат строки , поэтому он может хранить только 20-байтовый указатель на первичной странице данных.

  • Типы данных переменного размера также имеют префикс 1 или более байтов для кодирования длины. И формат строки InnoDB также имеет массив смещений полей. Так что в их вики есть более или менее задокументированная внутренняя структура . [ПРАВКА] Мертвая ссылка - здесь выглядит лучше.

Barracuda также поддерживает ROW_FORMAT = COMPRESSED для повышения эффективности хранения данных переполнения.

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

Билл Карвин
источник
2
Для инженеров, которые не разбираются в БД, очень просто пойти по пути данных. это никогда не выполняет. Моя собственная устаревшая база данных, в которой есть похожая ситуация, не соответствует размеру строки, поэтому менее драматична, но, черт возьми, это благо производительности! Я бы сказал, что ваш инженер по отчетам должен признать, что ему придется выполнять объединения и просто компенсировать эту работу хорошо во время индексации.
TechieGurl
1

Моя ситуация немного отличается. Один из элементов данных, который мне нужно хранить в каждой строке, потенциально очень большой. (Поле данных является LONGBLOB для документа, который может содержать несколько встроенных изображений. Моя примерная база данных содержит документы размером до 25–30 МБ, но в некоторых случаях эти документы могут быть больше.) Ни одно из решений, которые я нашел в Интернете, не помогло , (Изменен тип файла InnoDB на Barracuda, увеличен размер файла журнала, установлен формат строки в COMPRESSED.)

Единственное найденное мной решение, которое сработало, - вернуться к MySQL 5.5.x из MySQL 5.6.x.

Дэвид
источник