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


14

У будь-якій даній базі даних, яка містить записи користувачів у вигляді унікального поля автоматичного збільшення (заради прикладу, повідомлень між користувачами) ... що робити, коли настає час, і воно наблизиться до максимально підписаного чи неподписаного числа поточного типу даних? (32-бітний INT)? Я здогадуюсь, що сервер бази даних переповниться, коли він намагається призначити (2∧32) -1 номер наступному запису, тож як уникнути цього (без зміни типу даних заради питання) та продовжувати додавати записи? Що б ти зробив?

Чому я б використовував INT, а не, наприклад, VARCHARS?

Минуло кілька днів, як я поставив собі це гіпотетичне запитання, і хотів би знати, чим би займався професіонал.

Відповіді:


12

Як правило, ви використовуєте цілі числа, а не вархари, оскільки вони споживають менше місця, добре розуміють схему сортування, швидко індексувати і т.д. Цілі особи - це природні типи даних процесора, а значить, продуктивність, як правило, оптимальна. Зазвичай ціле число становить 4 байти, що еквівалентно лише 4 символам у (не-унікодовому) вархарі.

Якщо ви турбувались про те, що з типом 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?


Логічно, я б використовував ширший тип даних (для таблиці, яка дозволить БЕЗ ТОМУ кількість даних), але, оскільки це було гіпотетичним питанням, я хотів трохи зрозуміти. Якщо це буде підписано, це може спрацювати (але я б трохи дивно мав первинний ключ із негативними цифрами, IMHO), і я думаю, що це досить розумно. Це дасть час для DBA, щоб архівувати позитивні дані та починати заново. Якщо без підпису, ну ... проблеми.
AeroCross

Крім того, щоб використовувати приріст -1 від -1, починайте з (-2147483648) і збільшенням на 1. Але так, після перетину INT_MAX тоді ви досить добре втручаєтесь і вам потрібно переглянути дизайн і видалити старий індекс, замінивши його з новим більшим. і якщо ви перейдете без підпису BIGINT, я хочу прийти працювати над вашою командою;)
jcolebrand

PostgreSQL використовує послідовності для генерування ідентифікаційних номерів; оператор CREATE SEQUENCE дозволяє вказати CYCLE, який просто завернеться, якщо ви досягнете максимального значення. (Або мінімальне значення, якщо ви їдете в інший бік.) Опція CYCLE зараз в стандартах SQL. (По крайней мере, 2003 р.)
Майк Шеррілл 'Відкликання котів'

4

Переповнення BIGINT? Ха-ха. Спочатку з’ясуйте, як досягти безсмертя. INT НЕВИЗНАЧЕНО (4 мільярди) досить важко досягти. 100 ВСТАВ в секунду наблизилися б до переповнення INT за рік. BIGINT зайняло б кілька мільярдів років.

Щоб виправити: ALTER TABLE foo MODIFY COLUMN id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT; Але це займе години, тому що вона скопіює таблицю (яка має близько 4 мільярдів рядків, правда?) Та відновить усі вторинні індекси. Планувати заздалегідь.

Як правило, коли ви намагаєтесь зберегти занадто велике число для поля (наприклад, 999 у TINYINT UNSIGNED), воно мовчки обмежує його до максимуму для поля (255 у цьому випадку). Може бути "Попередження", але більшість людей не намагаються перевіряти попередження. Якщо це УНІКАЛЬНЕ поле, або є ІНОЗЕМНІ КЛЮКИ, ви можете отримати більш серйозну помилку.

CHAR або VARCHAR мовчки приковується до наявного місця.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.