[Django] #33835: Select_related().only() in the Prefetch class increases the number of queries for the InverseManyToOne relation.

5 views
Skip to first unread message

Django

unread,
Jul 8, 2022, 3:34:52 PM7/8/22
to django-...@googlegroups.com
#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.

Django

unread,
Jul 8, 2022, 3:35:22 PM7/8/22
to django-...@googlegroups.com
#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 layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Ipakeev):

* Attachment "PR1.PNG" added.

Django

unread,
Jul 8, 2022, 3:35:29 PM7/8/22
to django-...@googlegroups.com
#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 layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Ipakeev):

* Attachment "PR2.PNG" added.

Reply all
Reply to author
Forward
0 new messages