#33835: Select_related().only() in the Prefetch class increases the number of
queries for the InverseManyToOne relation.
-------------------------------------+-------------------------------------
Reporter: Ipakeev | Owner: nobody
Type: Bug | Status: new
Component: Database | Version: dev
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I'm trying to optimize graphQL queries. When I use Prefetch with
**select_related** and **only** optimizations, I encounter an increase in
database queries. This is because I'm prefetching Book via
InverseManyToOne relation and It needs a **publisher_id** in the **only**
method.
{{{
class Author(models.Model):
name = models.CharField(max_length=32)
class Book(models.Model):
title = models.CharField(max_length=32)
author = models.ForeignKey("Author", on_delete=models.CASCADE)
publisher = models.ForeignKey(
"Publisher",
on_delete=models.CASCADE,
related_name="books",
)
class Publisher(models.Model):
address = models.CharField(max_length=32)
class AuthorType(DjangoObjectType):
class Meta:
model = Author
class BookType(DjangoObjectType):
class Meta:
model = Book
class PublisherType(DjangoObjectType):
class Meta:
model = Publisher
}}}
Fill in the database:
{{{
with transaction.atomic():
authors = Author.objects.bulk_create([
Author(name=f"Name{i}") for i in range(10)
])
publishers = Publisher.objects.bulk_create([
Publisher(address=f"Address{i}") for i in range(10)
])
Book.objects.bulk_create([
Book(
title=f"Title{i}",
author=random.choice(authors),
publisher=random.choice(publishers),
) for i in range(20)
])
}}}
GraphQL query:
{{{
{
publishers {
address
books {
title
author {
name
}
}
}
}
}}}
22 db queries:
{{{
class Query(graphene.ObjectType):
publishers = graphene.List(PublisherType)
def resolve_publishers(self, info):
queryset = Book.objects.select_related("author").only("title",
"author__name")
return Publisher.objects.prefetch_related(Prefetch("books",
queryset)).only("address")
}}}
2 db queries:
{{{
class Query(graphene.ObjectType):
publishers = graphene.List(PublisherType)
def resolve_publishers(self, info):
queryset = Book.objects.select_related("author").only("title",
"author__name", "publisher_id")
return Publisher.objects.prefetch_related(Prefetch("books",
queryset)).only("address")
}}}
I fixed function **prefetch_related_objects** at django/db/models/query.py
and now I don't need **publisher_id** in **only** method:
{{{
...
prefetcher, descriptor, attr_found, is_fetched = get_prefetcher(
first_obj, through_attr, to_attr
)
from django.db.models.fields.related_descriptors import
ReverseManyToOneDescriptor
if type(descriptor) is ReverseManyToOneDescriptor:
lookup.queryset.query.deferred_loading[0].add(descriptor.field.attname)
if not attr_found:
raise AttributeError(
...
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33835>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070181df4ec14c-0553a6c8-b9aa-44f4-b755-ba62040b91c9-000000%40eu-central-1.amazonses.com.