AntonioK
@AntonioK

О выборе правильной длины BIGINT поля в MySQL

Известно, что для MySQL в общем случае не существует линейной зависимости дискового объема, затраченного на хранение данных, от символьной длины этих данных. Классическим примером данной особенности является поведение полей VARCHAR: строка ‘abcd’ занимает 5 байт, будучи помещенной в VARCHAR-поле, и 4 байта, если хранится в CHAR(4) поле. Подробно это явление описано в мануале по адресу dev.mysql.com/doc/refman/5.1/en/char.html

Однако, затратами на хранение самой строки дело не ограничивается — есть ещё индексы, есть внешние связи, и наверняка ещё что-то, что остается за пределами поля зрения клиента. Что-то, что реагирует на правильный выбор типа и длины поля различным количеством потребляемого дискового пространства.

Мой вопрос в следующем: есть таблица с полем INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, в которой закончились допустимые значения — всего их для UNSIGNED поля может быть 4294967295, что можно узнать в мануале по адресу dev.mysql.com/doc/refman/5.1/en/numeric-types.html и на реальном опыте, вставив id в таблицу и попытавшись следующую вставку проделать с использованием auto_increment — получим Duplicate entry '4294967295'. Удалить часть данных из таблицы нельзя, мне необходимо писать в неё дальше. Соответственно, нужно делать ALTER TABLE и менять тип поля на BIGINT, для которого максимальная длина UNSIGNED значения составляет 20 цифр, а максимально значение — 18446744073709551615. Но мне столько не нужно! Айдишники прибавляются с такой скоростью, что мне бы вполне хватило какого-нибудь BIGINT(14) на ближайшие полгода, а там видно будет. Так вот — какова практическая разница использования BIGINT(M) и BIGINT(20), где 10 < M < 20? Есть сильное подозрение, что использование BIGINT(20) создаст ощутимый перерасход диска и оверхед на I/O в сравнении с BIGINT-полем меньшей длины, но я не смог найти подтверждения этому подозрению.

Известно лишь, что на хранение INT(11) тратится не более 4 байт, а INT(20) — не более 8.

Об окружении: MySQL 5.1.57, движок InnoDB, проблемное поле является PRIMARY-ключом, на него существуют ссылки по FOREIGN KEY из других таблиц с каскадными CONSTRAINT на UPDATE.

Буду рад услышать ваши мысли по поводу правильного алгоритма выбора длины BIGINT, правильности моих мыслей и о механизмах MySQL, которые имеют дело с заявленной клиентом длиной поля.

А пока что, наученный горьким опытом внезапной остановки продакшена из-за того, что поле уперлось в INT(11), могу пожелать всем администраторам почаще проверять значения автоинкрементных счетчиков в их базах, чтобы не повторить мою судьбу, получив аварию с серьезным даунтаймом на пустом месте.
  • Вопрос задан
  • 23560 просмотров
Решения вопроса 1
JhaoDa
@JhaoDa
LaravelRUS Team
Если я правильно понял мануал, то M это «display width» и «display width does not constrain the range of values that can be stored in the column». Т.е. под BIGINT всегда будет отведено 8 байт.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы