len()
, count()
etc. Certifique-se de fazer o melhor uso deles.
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, ) charged_amount = models.PositiveIntegerField()
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, db_index=True, #DB Indexing ) charged_amount = models.PositiveIntegerField()
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, db_index=True, #DB Indexing ) charged_amount = models.PositiveIntegerField() class Meta: indexes = [ ["sold_at", "charged_amount"]]
ip:port
em que ip
é o endereço IP do daemon do Memcached e port
é a porta na qual o Memcached está sendo executado ou a URL que aponta para sua instância do Redis, usando o esquema apropriado.
Para habilitar o cache do banco de dados com o Memcached, instale pymemcache
usando o pip usando o seguinte comando:
pip install pymemcache
Em seguida, você pode definir as configurações de cache em seu settings.py
da seguinte maneira:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache', 'LOCATION': '127.0.0.1:11211', } }
No exemplo acima, o Memcached está sendo executado na porta 11211 do host local (127.0.0.1), usando a ligação pymemcache
:
pip install redis
Em seguida, defina as configurações de cache em seu settings.py
adicionando o seguinte código:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379', } }
Um queryset no Django, normalmente, armazena em cache seu resultado quando a avaliação acontece e para qualquer operação posterior com esse queryset, ele primeiro verifica se há resultados em cache. No entanto, quando você usa iterator()
, ele não verifica o cache e lê os resultados diretamente do banco de dados, nem salva os resultados no queryset.
Agora, você deve estar se perguntando como isso é útil. Considere um queryset que retorna um grande número de objetos com muita memória para armazenar em cache, mas deve ser usado apenas uma vez, nesse caso, você deve usar um iterator()
.
queryset = Product.objects.all() for each in queryset: do_something(each)
Considerando que, se usarmos iterator()
, o Django manterá a conexão SQL aberta e lerá cada registro e chamará do_something()
antes de ler o próximo registro:
queryset = Product.objects.all().iterator() for each in queryset: do_something(each)
O Django cria uma nova conexão de banco de dados para cada solicitação e a fecha após a conclusão da solicitação. Esse comportamento é causado por CONN_MAX_AGE
, que tem um valor padrão de 0. Mas quanto tempo deve ser definido? Isso é determinado pelo volume de tráfego em seu site; quanto mais alto o volume, mais segundos são necessários para manter a conexão. Geralmente é recomendado começar com um número baixo, como 60.
Você precisa agrupar suas opções extras em OPTIONS
, conforme detalhado no
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dashboard', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'CONN_MAX_AGE': '60', } } }
Nota: Essas expressões são definidas em django.db.models.expressions
e django.db.models.aggregates
, mas por conveniência, elas estão disponíveis e normalmente importadas de django.db.models
.
Na API do Django Queryset, as expressões F()
são usadas para se referir diretamente aos valores do campo do modelo. Ele permite que você se refira a valores de campo de modelo e conduza ações de banco de dados neles sem ter que buscá-los no banco de dados e na memória Python. Em vez disso, o Django emprega o objeto F()
para produzir uma frase SQL que define a atividade necessária do banco de dados.
products = Product.objects.all() for product in products: product.price *= 1.2 product.save()
Porém, se utilizarmos F()
, podemos fazer isso em uma única consulta da seguinte forma:
from django.db.models import F Product.objects.update(price=F('price') * 1.2)
select_related()
e prefetch_related()
O Django fornece os argumentos select_related()
e prefetch_related()
para otimizar seus conjuntos de consultas minimizando o número de solicitações do banco de dados.
select_related()
"segue" relacionamentos de chave estrangeira, selecionando dados adicionais de objetos relacionados ao executar sua consulta.
prefetch_related()
faz uma pesquisa separada para cada relacionamento e faz a "junção" em Python.
select_related()
Usamos select_related()
quando o item a ser selecionado é um único objeto, o que significa um campo ForeignKey
, OneToOne
e um campo OneToOne
.
Você pode usar select_related()
para criar uma única consulta que retorne todos os objetos relacionados para uma única instância para conexões um-para-um e um-para-um. Quando a consulta é executada, select_related()
recupera quaisquer dados extras de objetos relacionados de relacionamentos de chave estrangeira.
select_related()
funciona gerando uma junção SQL e inclui as colunas do objeto relacionado na expressão SELECT
. Como resultado, select_related()
retorna itens relacionados na mesma consulta de banco de dados.
Embora select_related()
produza uma consulta mais sofisticada, os dados adquiridos são armazenados em cache, portanto, o manuseio dos dados obtidos não requer nenhuma solicitação extra de banco de dados.
queryset = Tweet.objects.select_related('owner').all()
prefetch_related()
Em contraste, prefetch_related()
é utilizado para conexões muitos-para-muitos e muitos-para-um. Ele produz uma única consulta que inclui todos os modelos e filtros fornecidos na consulta.
Book.objects.prefetch_related('author').get(id=1).author.first_name
Leia sobre a diferença entre select_related()
e prefetch_related()
em detalhes .
bulk_create()
e bulk_update()
bulk_create()
é um método que cria a lista de objetos fornecida no banco de dados com uma consulta. Da mesma forma, bulk_update()
é um método que atualiza os campos fornecidos nas instâncias de modelo fornecidas com uma consulta.
class Post(models.Model): title = models.CharField(max_length=300, unique=True) time = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title
Agora, digamos que queremos adicionar vários registros de dados a este modelo, então podemos usar bulk_create()
assim:
#articles articles = [Post(title="Hello python"), Post(title="Hello django"), Post(title="Hello bulk")] #insert data Post.objects.bulk_create(articles)
>>> Post.objects.all() <QuerySet [<Post: Hello python>, <Post: Hello django>, <Post: Hello bulk>]>
E se quisermos atualizar os dados, podemos usar bulk_update()
assim:
update_queries = [] a = Post.objects.get(id=14) b = Post.objects.get(id=15) c = Post.objects.get(id=16) #set update value a.title="Hello python updated" b.title="Hello django updated" c.title="Hello bulk updated" #append update_queries.extend((a, b, c)) Post.objects.bulk_update(update_queries, ['title'])
>>> Post.objects.all() <QuerySet [<Post: Hello python updated>, <Post: Hello django updated>, <Post: Hello bulk updated>]>