Co zrobić, gdy pole w tabeli zbliża się do maksymalnej 32-bitowej liczby całkowitej ze znakiem lub bez znaku?

14

W dowolnej bazie danych, która przechowuje rekordy użytkownika w postaci unikalnego pola automatycznego przyrostu (na przykład wiadomości między użytkownikami) ... co zrobić, gdy nadejdzie czas i zbliży się do maksymalnej liczby podpisanych lub niepodpisanych bieżącego typu danych? (A 32-bit INT)? Zgaduję, że serwer bazy danych przepełni się, gdy spróbuje przypisać numer (2∧32) -1 do następnego wpisu, więc jak tego uniknąć (bez zmiany typu danych, ze względu na pytanie) i dodawać rekordy? Co byś zrobił?

Dlaczego miałbym używać INT, a nie na przykład VARCHARS?

Minęło kilka dni, odkąd zadałem sobie to hipotetyczne pytanie i chciałbym wiedzieć, co zrobiłby profesjonalista.

AeroCross
źródło

Odpowiedzi:

12

Na ogół używasz liczb całkowitych zamiast varcharów, ponieważ zajmują mniej miejsca, dobrze zrozumiały wzorzec sortowania jest szybki do indeksowania itp. Liczby całkowite są naturalnymi typami danych procesora, a zatem wydajność jest na ogół optymalna. Zazwyczaj liczba całkowita to 4 bajty, co odpowiada tylko 4 znakom w varchar (innym niż Unicode).

Jeśli martwiłeś się brakiem miejsca z typem INT, spróbuj BIGINT, który daje 8-bajtowe liczby. Limit jest dość duży i prawdopodobnie zabraknie miejsca na dysku, zanim osiągniesz ten limit rekordów :-) Wydajność BIGINT również będzie bardzo dobra, zwłaszcza, że ​​wiele serwerów jest teraz również 64-bitowych .

Odpowiedź na pierwszą część pytania o to, co dzieje się, gdy zabraknie INT, nie jest prosta, szczególnie, jak powiedziałeś, nie zmieniając typu danych na BIGINT. Zasadniczo niewiele możesz zrobić, a to, co możesz zrobić, jest bardzo ograniczone ze względu na charakter danych w bazie danych. Jakie rekordy są obce do tych danych? Czy nadal potrzebujesz wszystkich danych w tej tabeli i powiązanych rekordach? Zakładając, że można zarchiwizować wiele początkowych danych (i powiązanych z nimi danych), jedyne, co mogę zasugerować, to przeniesienie danych ze tabeli (powiedzmy, że od 1 do X milionów rekordów), a następnie zresetowanie zarodka tożsamości do 1. Istnieje wiele różnych powodów, choć nie poleciłbym tego - na przykład widziałem wiele bitów kodu, które robią takie rzeczy, jak sprawdzanie maksymalnej wartości pola id, aby zobaczyć, co właśnie zostało dodane, a to nie zadziała (i nie powinno być zrobione). Ponadto ludzie zakładają, że rekord N został utworzony przed N + 1. Myślę, że nie ma łatwej odpowiedzi.

Wreszcie, nie wiem o MySQL, ale SQL Server dałby błąd przepełnienia, jeśli osiągnąłeś limit.

Mile D.
źródło
1
Cieszę się z tak szczegółowej odpowiedzi. Dziękujemy za wyjaśnienie oferty VARCHAR, INT i BIGINT. Ponieważ pytanie jest hipotetyczne, zastanawiam się, co by się stało, gdyby osiągnięto również limit BIGINT. Pytanie pojawiło się w poście, który widziałem o facebooku używającym INT i osiągnięciu limitu, i widzę to jako całkowicie możliwe. Archiwizacja działałaby lub tworzenie drugiej tabeli z instrukcją warunkową (która, jak powiedziałeś, wymagałaby również aktualizacji skryptów i byłaby dość złożona). Ogólnie rzecz biorąc, świetna odpowiedź. Doceniam poświęcony czas.
AeroCross
9

Jednym z pomijanych punktów jest to, że wielu ludzi rozpoczyna automatyczny numer lub tożsamość od 1, tym samym tracąc natychmiast połowę możliwego zasięgu (dla podpisanych)

Po prostu przedefiniujesz liczbę, aby rozpocząć od -1, w tym przypadku zwiększaj -1.

Prawdopodobnie, jeśli kiedykolwiek spodziewałeś się wypełnić swoją kolumnę tożsamości, powinieneś to zaprojektować i na początku użyć szerszego typu danych.

Zobacz ostatnie pytanie dotyczące SO: SQL Server 2008: co się stanie, jeśli tożsamość przekroczy maksymalną wartość int?

gbn
źródło
Logiczne jest, że użyłbym szerszego typu danych (dla tabeli, która zawierałaby TAKĄ ilość danych), ale ponieważ było to pytanie hipotetyczne, potrzebowałem trochę wglądu. Jeśli jest podpisany, to może działać (ale trochę dziwnie byłoby mieć klucz główny z liczbami ujemnymi, IMHO) i myślę, że to całkiem sprytne. Dałoby to czas DBA na zarchiwizowanie pozytywnych danych i rozpoczęcie od nowa. Jeśli niepodpisane, cóż ... problemy.
AeroCross
Alternatywnie do użycia przyrostu -1 z -1, zacznij od (-2147483648) i przyrostu o 1. Ale tak, po przekroczeniu INT_MAX jesteś całkiem niezły i musisz ponownie zajrzeć do projektu i usunąć stary indeks zastępujący go z nowym większym. a jeśli zdasz niepodpisany BIGINT, to chcę przyjść do pracy w twoim zespole;)
jcolebrand
PostgreSQL używa sekwencji do generowania numerów identyfikacyjnych; instrukcja CREATE SEQUENCE pozwala określić CYKL, który po prostu zawinie, jeśli osiągniesz maksymalną wartość. (Lub minimalna wartość, jeśli idziesz w innym kierunku.) Opcja CYCLE jest teraz w standardach SQL. (Od co najmniej 2003 r.)
Mike Sherrill „Cat Recall”
4

Przepełnienie BIGINT? Ha ha. Najpierw wymyśl, jak osiągnąć nieśmiertelność. INT UNSIGNED (4 miliardy) jest wystarczająco trudny do osiągnięcia. 100 INSERTÓW na sekundę zbliżyłoby się do przepełnienia INT w ciągu roku. BIGINT zajmie kilka miliardów lat.

Aby naprawić: ALTER TABLE foo MODIFY COLUMN id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT; Ale zajmie to godziny, ponieważ skopiuje tabelę (która ma prawie 4 miliardy wierszy, prawda?) I odbuduje wszystkie indeksy wtórne. Planować naprzód.

Zasadniczo, gdy próbujesz zapisać liczbę zbyt dużą dla pola (np. 999 w TINYINT UNSIGNED), po cichu ograniczy ją do maksimum dla pola (w tym przypadku 255). Może pojawić się „Ostrzeżenie”, ale większość ludzi nie zawraca sobie głowy sprawdzaniem ostrzeżeń. Jeśli jest to pole UNIKALNE lub istnieją KLUCZE ZAGRANICZNE, może wystąpić poważniejszy błąd.

CHAR lub VARCHAR są po cichu obcinane do dostępnego miejsca.

Rick James
źródło