在与同行讨论N + 1以及糟糕的数据库查询的严重性能影响后,我访问了http://guides.rubyonrails.org/active_record_querying.html。
ActiveRecord(Rails):
clients = Client.includes(:address).limit(10)
如果客户端有地址,并且我打算在循环访问客户端时访问它们,Rails提供includes
让它知道继续并将它们添加到查询中,这样可以立即消除9个查询。
Django的:
https://github.com/lilspikey/django-batch-select提供批量查询支持。你知道其他库或技巧来实现上面提供的Rails,但是在一个不那么冗长的庄园中(如在rails示例中只有19个字符修复N + 1并且非常清楚)?此外,批量选择是以同样的方式解决问题,还是这两个不同的事情?
顺便说一下,我不是在问select_related
,虽然乍一看似乎是答案。我说的是address
有一个client
的forign键的情况。
答案 0 :(得分: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更灵活。详细但很有效。
答案 1 :(得分: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]
答案 2 :(得分:2)
django-batch-select应该提供这个问题的答案,尽管我还没有尝试过。伊格纳西奥的答案对我来说似乎最好。