Mysql
 sql >> Datenbank >  >> RDS >> Mysql

So ersetzen Sie den Primärschlüssel von Django durch eine andere Ganzzahl, die für diese Tabelle eindeutig ist

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.