2009-12-29 2 views
2

Я делаю приложение для запуска как на SQL Server, так и на PostgreSQL, поэтому я задаю этот вопрос обо всех из них.Будет ли уникальный RID когда-либо «переполняться»?

Что происходит всякий раз, когда вы создаете уникальный первичный ключ (с использованием типа последовательности или объекта с автоматическим приращением), и вы набираете более 4 миллиардов записей (32 бита)? Я не говорю, что в нашей таблице будет 4 миллиарда записей, а в том, что было создано 4 миллиарда записей, потому что RID только увеличивается. Поэтому, даже если я удалю 3,9 миллиарда этих записей, мои RID все еще находятся в диапазоне 4 миллиарда. Так что же происходит? Означает ли он точность до 64 бит или перекатывается до 0 или просто выплюнет очень критическую ошибку? Должен ли я беспокоиться о том, что даже 64-битный RID может также переполняться?

Также, как я могу бороться с этим? Есть ли какой-то способ очистки или инструмент? Должен ли я просто создавать свою собственную вещь каждый год или полностью перестраивать таблицу, чтобы получить согласованные МПОГ? (и, следовательно, также касаются многих других таблиц, которые используют эти RID, являются внешними ключами)

+2

Да, 32-разрядные автоинкрементные значения будут переполняться. http://stackoverflow.com/questions/261815/upper-limit-for-autoincrement-primary-key-in-sql-server – jball

+0

Вы не сможете переполнить 64-битное число за всю свою жизнь, оно слишком велико , –

+1

За всю свою жизнь? Или примерно через 10 лет? Я определенно не хочу исправлять эту ошибку через 10 лет, когда база данных заполнена очень важными данными. – Earlz

ответ

3

PostgreSQL, по умолчанию, ошибки и не переполнения:

# create sequence willyouwrap; 
CREATE SEQUENCE 
# select setval('willyouwrap', 9223372036854775807); 
     setval   
--------------------- 
9223372036854775807 
(1 row) 
# select nextval('willyouwrap'); 
ERROR: nextval: reached maximum value of sequence "willyouwrap" (9223372036854775807) 

Из документов:

Sequences are based on bigint arithmetic, so the range cannot exceed the range of an eight-byte integer (-9223372036854775808 to 9223372036854775807). On some older platforms, there might be no compiler support for eight-byte integers, in which case sequences use regular integer arithmetic (range -2147483648 to +2147483647).

Однако , вы можете выполнить цикл:

The CYCLE option allows the sequence to wrap around when the maxvalue or minvalue has been reached by an ascending or descending sequence respectively. If the limit is reached, the next number generated will be the minvalue or maxvalue, respectively.

If NO CYCLE is specified, any calls to nextval after the sequence has reached its maximum value will return an error. If neither CYCLE or NO CYCLE are specified, NO CYCLE is the default.

Не боритесь с ним. Проведите лишние байты и сохраните все просто. Вы, скорее всего, пожалеете о добавлении дополнительных уровней сложности и/или задач обслуживания, чем наличие большего пространства ключей.

1

На SQL Server: это зависит от типа столбца RID. Внутренняя IDENTITY может увеличиваться, но не присвоить столбцу stoarge:

CREATE TABLE [t1] (
[tid] int IDENTITY (2147483647, 1) NOT NULL 
    , name varchar(1) 
) ON [PRIMARY] 
GO 
insert into t1(name) values('1') 
insert into t1(name) values('1') 

это вызывает ошибку:

Msg 8115, Level 16, State 1, Line 2 
Arithmetic overflow error converting IDENTITY to data type int. 
Arithmetic overflow occurred. 

Но числовой столбец с достаточным количеством памяти будет увеличиваться просто отлично:

CREATE TABLE [t1] (
[tid] numeric(38,0) IDENTITY (2147483647, 1) NOT NULL 
    , name varchar(1) 
) ON [PRIMARY] 
GO 
insert into t1(name) values('1') 
insert into t1(name) values('1') 

Аналогично BIGINT будет overlfow в 2 ^^ 63-1:

CREATE TABLE [t1] (
[tid] bigint IDENTITY (9223372036854775807, 1) NOT NULL 
    , name varchar(1) 
) ON [PRIMARY] 
GO 
insert into t1(name) values('1') 
insert into t1(name) values('1') 

но числовой столбец с достаточным количеством памяти будет успешным:

CREATE TABLE [t1] (
[tid] numeric(38,0) IDENTITY (9223372036854775807, 1) NOT NULL 
    , name varchar(1) 
) ON [PRIMARY] 
GO 
insert into t1(name) values('1') 
insert into t1(name) values('1') 
Смежные вопросы