2009-12-29 1 views
2

Je fais une application pour fonctionner à la fois sur SQL Server et PostgreSQL, donc je pose cette question à propos des deux. Que se passe-t-il lorsque vous créez une clé primaire unique (à l'aide d'une séquence ou d'une chose de type auto-incrémentation) et que vous atteignez plus de 4 milliards d'enregistrements (32 bits)? Je ne dis pas que notre table aura 4 milliards d'enregistrements mais plutôt que 4 milliards d'enregistrements ont été créés parce que le RID ne fait que s'incrémenter. Donc, même si j'ai supprimé 3,9 milliards de ces enregistrements, mes RID sont toujours dans la fourchette de 4 milliards. Alors qu'est-ce qui se passe? Est-ce que la précision est de 64 bits ou est-ce que ça revient à 0 ou crache une erreur très critique? Dois-je m'inquiéter que même un RID 64 bits peut éventuellement déborder?Est-ce que des RID uniques vont jamais "déborder"?

Aussi, comment puis-je me battre contre cela? Existe-t-il une option ou un outil de nettoyage? Est-ce que je dois juste créer ma propre chose à chaque année ou reconstruire complètement la table pour obtenir des RIDs cohérents? (et donc aussi toucher beaucoup d'autres tables qui utilisent ces RID sont des clés étrangères)

+2

Oui, les valeurs auto-incrémentées de 32 bits débordent. http://stackoverflow.com/questions/261815/upper-limit-for-autoincrement-primary-key-in-sql-server – jball

+0

Vous ne serez pas en mesure de déborder un nombre de 64 bits dans toute votre vie, c'est juste trop grand . –

+1

Dans toute ma vie? Ou dans environ 10 ans? Je ne vais certainement pas vouloir corriger ce bug dans 10 ans lorsque la base de données est pleine de données très critiques – Earlz

Répondre

3

PostgreSQL, par défaut, l'erreur et non overflow:

# 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) 

De la documentation:

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).

Cependant , vous pouvez faire le cycle:

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.

Ne le combat pas. Passez les octets supplémentaires et gardez les choses simples. Vous avez plus tendance à regretter d'ajouter des couches supplémentaires de complexité et/ou de tâches de maintenance que d'avoir un espace de clé plus grand.

1

Sur SQL Server: Cela dépend du type de la colonne RID. L'identité interne peut augmenter, mais ne parviendra pas à attribuer à la colonne 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') 

ce qui déclenche l'erreur:

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

Mais une colonne numérique avec suffisamment de stockage sera incrémenter très bien:

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') 

de même, un bigint sera 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') 

mais une colonne numérique avec stockage suffisante réussira:

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') 
Questions connexes