#22757: prefetch_related isn't as effecient as it could be with 
GenericForeignKey
and proxy models
-------------------------------------+-------------------------------------
     Reporter:  gwahl@…              |                    Owner:  (none)
         Type:                       |                   Status:  new
  Cleanup/optimization               |
    Component:  Database layer       |                  Version:  dev
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  prefetch_related     |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Nolan Little):

 * owner:  Nolan Little => (none)
 * status:  assigned => new


Comment:

 I started working on this at DjangoCon US. I had difficulty coming up with
 a true optimization. I started from
 `GenericForeignKey.get_prefetch_queryset` like Simon recommended. Grouping
 the queries by concrete model was fairly straightforward, the difficulty
 began with turning all instances back into their correct concrete/proxy
 types correctly.

 The only method I could come up with required iterating over every object
 and checking if its instance type was `proxy`. I created a dict of the
 instances content types to instance PK during the query grouping so that I
 could use it to identify the correct `ContentType`. In the below code
 `fkeys` was a list of grouped ids for all concrete and proxy objects:

 {{{
 objs = concrete_ct.get_all_objects_for_this_type(pk__in=fkeys)
     for obj in objs:
           instance = instance_dict[obj.pk]
           if instance.content_type.model_class()._meta.proxy:
                obj.__dict__.pop("_state")  # necessary?
                ret_obj =
 instance.content_type.model_class()(**obj.__dict__)
           else:
                ret_obj = obj
           ret_val.append(ret_obj)
 }}}

 There may be a cleaner way to get the correct Instance type back that I'm
 unaware of as this piece felt quite ugly:
 {{{
 obj.__dict__.pop("_state")  # necessary?
 ret_obj = instance.content_type.model_class()(**obj.__dict__)
 }}}

 Unless there is a way to avoid iterating over all objects to determine the
 correct instance I question the viability of optimizing the amount of
 queries here. Realistically it seems that the amount of objects returned
 is likely to be far higher than the amount of proxy models queried.

 If i'm way off on this approach or if there is a way to get the correct
 type for return instances without iterating all objects I'd love to learn
 about it! I don't anticipate having a lot of time to make progress on this
 in the near future so I'm going to un-assign myself, but I'm happy to pick
 it back up in the future if anyone has recommendations on the approach.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/22757#comment:5>
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/0107018b959bf7c2-1ce0877a-e789-46b5-8c2e-35c93399b6aa-000000%40eu-central-1.amazonses.com.

Reply via email to