Django N + 1查询解决方案

oro*_*aki 13 django django-orm select-n-plus-1

在与同行讨论N + 1以及糟糕的数据库查询的严重性能影响后,我访问了http://guides.rubyonrails.org/active_record_querying.html.

ActiveRecord(Rails):

clients = Client.includes(:address).limit(10)
Run Code Online (Sandbox Code Playgroud)

在客户端具有地址的情况下,我打算在循环访问客户端时访问它们,Rails提供includes让它知道继续并将它们添加到查询中,这样可以立即消除9个查询.

Django的:

https://github.com/lilspikey/django-batch-select提供批量查询支持.你知道其他库或技巧来实现上面提供的Rails,但是在一个不那么冗长的庄园中(如在rails示例中只有19个字符修复N + 1并且非常清楚)?另外,批量选择是以同样的方式解决问题,还是这两个不同的事情?

顺便说一句,我不是在问select_related,虽然乍一看似乎是答案.我说的是address有一个forign键的情况client.

laf*_*ste 12

你可以使用prefetch_related从Django 1.4开始:https: //docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related

如果您使用<1.4,请查看此模块:https: //github.com/ionelmc/django-prefetch

它声称比Django的prefetch_related更灵活.详细,但效果很好.


Ign*_*ams 9

不幸的是,Django的ORM还没有办法做到这一点.

幸运的是,只需要在2个查询中完成它,在Python中完成一些工作.

clients = list(Client.objects.all()[:10])
addresses = dict((x.client_id, x) for x in
    Address.objects.filter(client__in=clients))
for client in clients:
  print client, addresses[client.id]
Run Code Online (Sandbox Code Playgroud)