sql >> Database teknologi >  >> RDS >> Mysql

Sådan erstatter du Djangos primære nøgle med et andet heltal, der er unikt for den tabel

Idéen

Jeg vil anbefale dig den samme tilgang, som bruges af Instagram . Deres krav ser ud til nøje at følge dine.

Genererede id'er bør kunne sorteres efter tid (så en liste over billed-id'er f.eks. kunne sorteres uden at hente mere information om billederne) ID'er bør ideelt set være 64 bit (for mindre indekser og bedre lagring i systemer som Redis) Systemet bør introduceres som få nye 'bevægelige dele' som muligt – en stor del af, hvordan vi har været i stand til at skalere Instagram med meget få ingeniører, er ved at vælge enkle, letforståelige løsninger, som vi stoler på.

De kom op med et system, der har 41 bit baseret på tidsstemplet, 13 o databasen shard og 10 for en automatisk stigningsdel. Da du ikke ser ud til at bruge skår. Du kan bare have 41 bits for en tidsbaseret komponent og 23 bits valgt tilfældigt. Det giver en yderst usandsynlig 1 ud af 8,3 millioner chance for at få en konflikt, hvis du indsætter poster på samme tid. Men i praksis er du aldrig tilbøjelig til at ramme dette. Lige så hvad med noget kode:

Generering af ID'er

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 

Bemærk, START_TIME i ovenstående kode er et vilkårligt starttidspunkt. Du kan bruge time.time()*1000 , få værdien og indstille den som START_TIME

Bemærk, at reverse_id metode, jeg har postet, giver dig mulighed for at finde ud af, hvornår posten blev oprettet. Hvis du har brug for at holde styr på disse oplysninger, kan du gøre det uden at skulle tilføje et andet felt til det! Så din primære nøgle er faktisk at gemme din lagerplads i stedet for at øge den!

Modellen

Nu er det sådan, din model ville se ud.

class MyClass(models.Model):
   id = models.BigIntegerField(default = fields.make_id, primary_key=True)  

Hvis du foretager ændringer i din database uden for django, skal du oprette det, der svarer til make_id som en sql-funktion

Som en fodnote. Dette er lidt ligesom den tilgang, som Mongodb brugte til at generere dets _ID for hvert objekt.



  1. SQL, Håndtering af tomme celler

  2. Begræns en sammenkædet server til et enkelt lokalt login (T-SQL-eksempel)

  3. Sådan fungerer LEFT()-funktionen i MySQL

  4. Hvad er nyt i PostgreSQL 13?