sql >> Database >  >> RDS >> Mysql

Hoe de primaire sleutel van Django te vervangen door een ander geheel getal dat uniek is voor die tabel?

Het idee

Ik zou je dezelfde aanpak aanbevelen die wordt gebruikt door Instagram . Hun eisen lijken de uwe nauw te volgen.

Gegenereerde ID's moeten op tijd kunnen worden gesorteerd (zo zou een lijst met foto-ID's bijvoorbeeld kunnen worden gesorteerd zonder meer informatie over de foto's op te halen) ID's zouden idealiter 64 bits moeten zijn (voor kleinere indexen en betere opslag in systemen zoals Redis) Het systeem zou moeten introduceren als zo min mogelijk nieuwe 'bewegende onderdelen' - een groot deel van hoe we Instagram hebben kunnen schalen met heel weinig ingenieurs, is door te kiezen voor eenvoudige, gemakkelijk te begrijpen oplossingen die we vertrouwen.

Ze kwamen met een systeem dat 41 bits heeft op basis van de tijdstempel, 13 o de database-shard en 10 voor een auto-increment-gedeelte. Aangezien je geen shards lijkt te gebruiken. U kunt slechts 41 bits hebben voor een op tijd gebaseerd bestanddeel en 23 willekeurig gekozen bits. Dat levert een uiterst onwaarschijnlijke kans van 1 op 8,3 miljoen op om een ​​conflict te krijgen als u tegelijkertijd records invoegt. Maar in de praktijk zul je dit nooit bereiken. Goed, wat dacht je van wat code:

ID's genereren

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 

Let op, START_TIME in de bovenstaande code is een willekeurige starttijd. U kunt time.time()*1000 gebruiken, de waarde ophalen en deze instellen als START_TIME

Merk op dat de reverse_id methode die ik heb gepost, stelt u in staat om erachter te komen op welk moment het record is gemaakt. Als u die informatie moet bijhouden, kunt u dat doen zonder dat u er een ander veld voor hoeft toe te voegen! Je primaire sleutel is dus eigenlijk het opslaan van je opslagruimte in plaats van het te vergroten!

Het model

Dit is hoe uw model eruit zou zien.

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

Als u buiten django wijzigingen aanbrengt in uw database, moet u het equivalent van make_id maken als een sql-functie

Als voetnoot. Dit lijkt een beetje op de benadering die Mongodb gebruikt om zijn _ID te genereren voor elk object.



  1. Hoe maak je een MySQL hiërarchische recursieve query?

  2. GROUP BY met MAX(DATUM)

  3. Query invoegen om rijen in MySQL in te voegen

  4. Beste gegevenstype om geldwaarden op te slaan in MySQL