Die Idee
Ich würde Ihnen den gleichen Ansatz empfehlen, der von Instagram verwendet wird . Ihre Anforderungen scheinen Ihren sehr ähnlich zu sein.
Generierte IDs sollten nach Zeit sortierbar sein (so könnte beispielsweise eine Liste von Foto-IDs sortiert werden, ohne weitere Informationen über die Fotos abzurufen). IDs sollten idealerweise 64 Bit lang sein (für kleinere Indizes und bessere Speicherung in Systemen wie Redis). möglichst wenige neue "bewegliche Teile" – ein großer Teil der Art und Weise, wie wir Instagram mit sehr wenigen Ingenieuren skalieren konnten, ist die Auswahl einfacher, leicht verständlicher Lösungen, denen wir vertrauen.
Sie haben sich ein System ausgedacht, das 41 Bits basierend auf dem Zeitstempel, 13 für den Datenbank-Shard und 10 für einen Auto-Increment-Teil hat. Da Sie anscheinend keine Shards verwenden. Sie können nur 41 Bits für eine zeitbasierte Komponente und 23 Bits zufällig auswählen. Dies führt zu einer äußerst unwahrscheinlichen Wahrscheinlichkeit von 1 zu 8,3 Millionen, dass ein Konflikt auftritt, wenn Sie gleichzeitig Datensätze einfügen. Aber in der Praxis werden Sie dies wahrscheinlich nie treffen. Richtig, wie wäre es mit etwas Code:
IDs generieren
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
Hinweis, START_TIME
im obigen Code ist eine willkürliche Startzeit. Sie können time.time()*1000 verwenden, den Wert abrufen und diesen als START_TIME
festlegen
Beachten Sie, dass die reverse_id
Methode, die ich gepostet habe, ermöglicht es Ihnen, herauszufinden, zu welcher Zeit der Datensatz erstellt wurde. Wenn Sie diese Informationen nachverfolgen müssen, können Sie dies tun, ohne ein weiteres Feld dafür hinzufügen zu müssen! Ihr Primärschlüssel spart also tatsächlich Ihren Speicherplatz, anstatt ihn zu erhöhen!
Das Modell
So würde Ihr Modell jetzt aussehen.
class MyClass(models.Model):
id = models.BigIntegerField(default = fields.make_id, primary_key=True)
Wenn Sie außerhalb von Django Änderungen an Ihrer Datenbank vornehmen, müssen Sie das Äquivalent von make_id
erstellen als SQL-Funktion
Als Fußnote. Dies ähnelt dem von Mongodb verwendeten Ansatz, um seine _ID zu generieren für jedes Objekt.