question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Techniques for enhancing Django query performance

See original GitHub issue

Hi folks!

I was curious as to how one would go about increasing query performance, when one is using DjangoObjectTypes directly connected to a model. One example of an optimization that I think would be easy is the following:

if 'arg x' is a field that is asked for:
    make sure that "something_set" is included in "select_related"

Any one willing to share ideas? Also, how would one go about creating a LRU cache?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

5reactions
jameswysecommented, Apr 30, 2017

I’ve extracted some code and simplified it a bit (our implementation is a bit more complex) but hopefully you find it useful. One day I’ll find the time to release this as a reusable package (or perhaps directly in to graphene-django)

helpers.py

from graphql.utils.ast_to_dict import ast_to_dict
from django.utils.six import iteritems


def collect_fields(node, fragments, variables):
    field = {}
    selection_set = node.get('selection_set') if node else None
    selections = selection_set.get('selections', None) if selection_set else None

    if selections is not None:
        for leaf in selections:
            leaf_kind = leaf.get('kind')
            leaf_name = leaf.get('name', {}).get('value')
            leaf_directives = leaf.get('directives')

            # Check if leaf should be skipped
            # - If name is '__typename'
            # - if @skip directive is used and evaluates to True
            # - if @include directive is used and evaluates to False (not yet implemented!)
            should_skip = False
            for directive in leaf_directives:
                if directive.get('name', {}).get('value') == 'skip':
                    for arg in directive.get('arguments', []):
                        arg_value = arg.get('value', {})
                        if arg.get('name', {}).get('value') == 'if':
                            if arg_value.get('kind') == 'Variable':
                                var_name = arg_value.get('name', {}).get('value')
                                should_skip = variables.get(var_name, should_skip)
                            elif arg_value.get('kind') == 'BooleanValue':
                                should_skip = arg_value.get('value')

            if leaf_name != '__typename' and not should_skip:
                if leaf_kind == 'Field':
                    field.update({leaf_name: collect_fields(leaf, fragments, variables)})
                elif leaf_kind == 'FragmentSpread':
                    field.update(collect_fields(fragments[leaf_name], fragments, variables))
    return field


def get_fields(info):
    """Return a nested dict of the fields requested by a graphene resolver"""
    fragments = {}
    node = ast_to_dict(info.field_asts[0])

    for name, value in iteritems(info.fragments):
        fragments[name] = ast_to_dict(value)

    fields = collect_fields(node, fragments, info.variable_values)

    return fields

Example usage

from django.db.models import Prefetch

def resolve_posts(self, args, context, info):
    qs = Post.objects.all()
    fields = get_fields(info)

    # posts { author }
    if fields.get('author', {}):
        qs = qs.select_related('author')

    # posts { comments }    
    if fields.get('comments', {}):
        all_comments = Comment.objects.all()

        # posts { comments { author } }
        if fields.get('comments', {}).get('author', {}):
            all_comments = all_comments.select_related('author')

        qs = qs.prefetch_related(Prefetch('comments', queryset=all_comments))

    return qs
0reactions
stale[bot]commented, Jul 29, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Performance and optimization - Django documentation
Using cached sessions may be a way to increase performance by eliminating the need to load session data from a slower storage source...
Read more >
How to Optimize Django ORM Queries - Gearheart
1. Using select_related() and prefetch_related() functions ... Django ORM provides two common methods to avoid the N+1 issue, which are ...
Read more >
How to Improve Django Performance. Optimization Tips
Have troubles with Django performance? While reading it, you'll get an understanding of how to improve your Django application and avoid typical mistakes....
Read more >
A Guide To Django Performance Tips For Optimization & Testing
One more way you can optimize the performance is by forcing delayed executions of fetching data from the database. Certain operations force the ......
Read more >
Optimize your Django application for better performance
Reduce the number of queries and optimize them · Go async wherever possible · Don't repeat yourself · Cache your predictable data ·...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found