Что делать, когда поле в таблице приближается к максимальному 32-разрядному целому числу со знаком или без знака?

14

В любой заданной базе данных, содержащей пользовательские записи в форме уникального поля автоинкремента (например, межпользовательские сообщения) ... что делать, когда наступит время и оно достигнет максимального числа со знаком или без знака текущего типа данных? (32-битный INT)? Я предполагаю, что сервер базы данных переполнится, когда попытается назначить число (2∧32) -1 для следующей записи, так, как этого избежать (без изменения типа данных, ради вопроса) и продолжать добавлять записи? Что бы вы сделали?

Почему я должен использовать INT, а не, например, VARCHARS?

Прошло несколько дней с тех пор, как я задавал себе этот гипотетический вопрос, и я хотел бы знать, что бы сделал профессионал.

AeroCross
источник

Ответы:

12

Обычно вы используете целые числа, а не varchars, потому что они занимают меньше места, хорошо понимают шаблон сортировки, быстро индексируются и т. Д. Целые числа являются естественными типами данных ЦП, и, следовательно, производительность в целом является оптимальной. Обычно целое число составляет 4 байта, что эквивалентно всего 4 символам в (не-Unicode) varchar.

Если вас беспокоит нехватка места с типом INT, попробуйте BIGINT, который даст вам 8-байтовые числа. Ограничение на это довольно велико, и вам, вероятно, не хватит места на диске, прежде чем вы достигнете этого предела записей :-) Производительность BIGINT также будет очень хорошей, особенно потому, что многие серверы теперь тоже 64-битные ,

Ответ на первую часть вашего вопроса о том, что происходит, когда вы заканчиваете в INT, не прост, особенно, как вы сказали, не меняя тип данных на BIGINT. По сути, вы мало что можете сделать, и то, что вы можете сделать, сильно ограничено характером данных в вашей базе данных. Какие записи имеют внешние ключи к этим данным? Вам все еще нужны все данные в этой таблице и связанные записи? Если предположить, что вы можете архивировать много исходных данных (и связанных с ними данных), то единственное, что я могу предложить, - это переместить данные из таблицы (скажем, от 1 до X миллионов записей), а затем сброс идентификатора идентификатора на 1. Существуют разные причины, хотя я бы не рекомендовал этого - например, я видел много битов кода, которые проверяют максимальное значение поля id, чтобы увидеть, что только что было добавлено, и это не сработает (и не должно быть сделано). Также люди предполагают, что запись N была создана до N + 1. Не простой ответ, я думаю.

Наконец, я не знаю о MySQL, но SQL Server выдаст ошибку переполнения, если вы достигнете предела.

Майлз Д
источник
1
Я доволен таким подробным ответом. Спасибо за объяснение сделки VARCHAR, INT и BIGINT. Поскольку вопрос является гипотетическим, мне интересно, что произойдет, если будет достигнут и предел BIGINT. Вопрос был поднят в сообщении, которое я увидел о том, что Facebook использует INT и достигает предела, и я считаю это вполне возможным. Будет работать архивирование или создание второй таблицы с условным оператором (что, как вы сказали, потребует также обновления скриптов, и это будет довольно сложно). В целом, отличный ответ. Я ценю потраченное время.
AeroCross
9

Один из упущенных моментов заключается в том, что многие люди начинают автоматический номер или идентичность с 1, таким образом, теряя половину возможного диапазона немедленно (для подписанного)

Вы просто переопределите число, чтобы начать с -1, с шагом -1 в этом случае.

Возможно, если вы когда-нибудь ожидали заполнить свой столбец идентификаторов, то вы должны были спроектировать это и использовать более широкий тип данных в начале.

Смотрите этот недавний вопрос на SO: SQL Server 2008: что произошло, если идентичность превысила максимальное значение int?

ГБН
источник
Логично, что я бы использовал более широкий тип данных (для таблицы, которая бы соответствовала ЭТОМУ количеству данных), но, поскольку это был гипотетический вопрос, я хотел кое-что понять. Если он подписан, это может сработать (но я бы немного странно имел первичный ключ с отрицательными числами, ИМХО), и я думаю, что это довольно умно. Для администратора базы данных будет дано время архивировать положительные данные и начать заново. Если без знака, ну ... проблемы.
AeroCross
В качестве альтернативы использованию приращения -1 от -1, начните с (-2147483648) и увеличивайте на 1. Но да, после того, как вы пересечете INT_MAX, у вас все будет хорошо, вам нужно пересмотреть проект и удалить старый индекс, заменив его. с новым большим. и если вы передадите неподписанный BIGINT, то я хочу работать в вашей команде;)
jcolebrand
PostgreSQL использует последовательности для генерации идентификационных номеров; оператор CREATE SEQUENCE позволяет вам указать CYCLE, который будет просто переходить, если вы достигнете максимального значения. (Или минимальное значение, если вы идете в другом направлении.) Опция CYCLE теперь в стандартах SQL. (По крайней мере, с 2003 года.)
Майк Шеррилл 'Cat Recall'
4

Переполнение BIGINT? Ха-ха. Сначала выясните, как достичь бессмертия. INT UNSIGNED (4 миллиарда) достаточно сложно достичь. 100 INSERT в секунду будут приближаться к переполнению INT через год. BIGINT займет несколько миллиардов лет.

Исправить: ALTER TABLE foo MODIFY COLUMN id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT; Но на это уйдут часы, потому что он скопирует таблицу (которая имеет около 4 миллиардов строк, верно?) И перестроит все вторичные индексы. План Ahea d.

Обычно, когда вы пытаетесь сохранить число, слишком большое для поля (например, 999 в TINYINT UNSIGNED), оно автоматически устанавливает максимальное значение для поля (в данном случае 255). Может быть «Предупреждение», но большинство людей не удосуживаются проверить предупреждения. Если это УНИКАЛЬНОЕ поле или есть ИНОСТРАННЫЕ КЛАВИШИ, вы можете получить более серьезную ошибку.

CHAR или VARCHAR молча обрезаются до доступного пространства.

Рик Джеймс
источник