L'idée
Je vous recommanderais la même approche que celle utilisée par Instagram . Leurs exigences semblent suivre de près les vôtres.
Les identifiants générés doivent pouvoir être triés par heure (ainsi, une liste d'identifiants avec photo, par exemple, pourrait être triée sans récupérer plus d'informations sur les photos) Les identifiants doivent idéalement être de 64 bits (pour des index plus petits et un meilleur stockage dans des systèmes comme Redis) Le système doit introduire comme peu de nouvelles « pièces mobiles » que possible :une grande partie de la façon dont nous avons réussi à faire évoluer Instagram avec très peu d'ingénieurs, c'est en choisissant des solutions simples et faciles à comprendre en lesquelles nous avons confiance.
Ils ont proposé un système qui comporte 41 bits basés sur l'horodatage, 13 sur le fragment de base de données et 10 pour une partie d'incrémentation automatique. Puisque vous ne semblez pas utiliser de fragments. Vous pouvez simplement avoir 41 bits pour un composant basé sur le temps et 23 bits choisis au hasard. Cela produit une chance extrêmement improbable de 1 sur 8,3 millions d'obtenir un conflit si vous insérez des enregistrements en même temps. Mais dans la pratique, vous n'êtes jamais susceptible de toucher cela. Bon alors que diriez-vous d'un peu de code :
Générer des identifiants
START_TIME = a constant that represents a unix timestamp
def make_id():
'''
inspired by http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram
'''
t = int(time.time()*1000) - START_TIME
u = random.SystemRandom().getrandbits(23)
id = (t << 23 ) | u
return id
def reverse_id(id):
t = id >> 23
return t + START_TIME
Remarque, START_TIME
dans le code ci-dessus est une heure de démarrage arbitraire. Vous pouvez utiliser time.time()*1000 , obtenir la valeur et la définir comme START_TIME
Notez que le reverse_id
La méthode que j'ai postée permet de savoir à quelle heure l'enregistrement a été créé. Si vous avez besoin de garder une trace de ces informations, vous pouvez le faire sans avoir à ajouter un autre champ ! Ainsi, votre clé primaire permet en fait d'économiser votre espace de stockage plutôt que de l'augmenter !
Le modèle
Voici à quoi ressemblerait votre modèle.
class MyClass(models.Model):
id = models.BigIntegerField(default = fields.make_id, primary_key=True)
Si vous apportez des modifications à votre base de données en dehors de Django, vous devrez créer l'équivalent de make_id
en tant que fonction sql
En note de bas de page. C'est un peu comme l'approche utilisée par Mongodb pour générer son _ID pour chaque objet.