Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como substituir a chave primária do Django por um inteiro diferente que é exclusivo para essa tabela

A ideia


Eu recomendaria a você a mesma abordagem usada pelo Instagram . Suas exigências parecem seguir de perto as suas.

IDs gerados devem ser classificáveis ​​por tempo (para que uma lista de IDs de fotos, por exemplo, possa ser classificada sem buscar mais informações sobre as fotos) IDs devem ser idealmente de 64 bits (para índices menores e melhor armazenamento em sistemas como Redis) O sistema deve apresentar como poucas 'peças móveis' possíveis - grande parte de como conseguimos dimensionar o Instagram com pouquíssimos engenheiros é escolhendo soluções simples e fáceis de entender nas quais confiamos.

Eles criaram um sistema que tem 41 bits com base no timestamp, 13 no fragmento do banco de dados e 10 para uma porção de incremento automático. Desde que você não parece estar usando shards. Você pode ter apenas 41 bits para um copmonent baseado em tempo e 23 bits escolhidos aleatoriamente. Isso produz uma chance extremamente improvável de 1 em 8,3 milhões de obter um conflito se você inserir registros ao mesmo tempo. Mas, na prática, você nunca vai acertar isso. Certo, então que tal algum código:

Gerando IDs

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 

Observe, START_TIME no código acima é algum tempo de início arbitrário. Você pode usar time.time()*1000 , obter o valor e defini-lo como START_TIME

Observe que o reverse_id O método que postei permite que você descubra em que momento o registro foi criado. Se você precisar acompanhar essas informações, poderá fazê-lo sem precisar adicionar outro campo para isso! Portanto, sua chave primária está realmente salvando seu armazenamento em vez de aumentá-lo!

O modelo


Agora é assim que seu modelo ficaria.
class MyClass(models.Model):
   id = models.BigIntegerField(default = fields.make_id, primary_key=True)  

Se você fizer alterações em seu banco de dados fora do django, você precisará criar o equivalente a make_id como uma função sql

Como nota de rodapé. Isso é um pouco parecido com a abordagem usada pelo Mongodb para gerar seu _ID para cada objeto.