如何避免重复 django prefetch 相关的数据库命中
How to avoid repeated django prefetch related database hits
当我获取客户端时,我还想预取所有相关的探测和探测通道,当我获取探测时,我还想获取所有相关的探测通道。
但似乎当我获得客户端对象或查看管理员时,它会从客户端和探针管理器运行 get_queryset 方法。所以它会预取 probechannels 两次。这可以从调试工具栏中的 sql 查询数量以及在 get_queryset 方法中添加打印语句中看出。
所以我有
class ClientManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super(ClientManager, self).get_queryset(*args, **kwargs).prefetch_related('probe_set__probechannel_set')
class Client(models.Model):
objects = ClientManager()
class ProbeManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super(ProbeManager, self).get_queryset(*args, **kwargs).prefetch_related('probechannel_set')
class Probe(models.Model):
Client = models.ForeignKey('Client')
objects = ProbeManager()
class ProbeChannel(models.Model):
Probe = models.ForeignKey('Probe')
有没有办法避免这种情况?我读过 _base_managers 用于相关对象,但这里的 _base_manager 只是 models.Manager。我正在使用 django 1.11 和这个叫做 python 2.7.
的时髦新东西
我仍然不确定这是否是所需的 Django 行为,但预取肯定会触发两次。我想出的避免 ProbeManager 预取被触发的答案很简单——避免使用这个管理器。
所以在 Probe class 我添加了
objects_without_prefetch = models.Manager()
然后使用预取对象 Prefetch('probe_set',Probe.objects_without_prefetch.all()) 而不是简单地使用调用其自己的预取的 'probe_set'。
无论如何感谢那些花时间思考这个问题并回答的人!
当我获取客户端时,我还想预取所有相关的探测和探测通道,当我获取探测时,我还想获取所有相关的探测通道。
但似乎当我获得客户端对象或查看管理员时,它会从客户端和探针管理器运行 get_queryset 方法。所以它会预取 probechannels 两次。这可以从调试工具栏中的 sql 查询数量以及在 get_queryset 方法中添加打印语句中看出。 所以我有
class ClientManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super(ClientManager, self).get_queryset(*args, **kwargs).prefetch_related('probe_set__probechannel_set')
class Client(models.Model):
objects = ClientManager()
class ProbeManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super(ProbeManager, self).get_queryset(*args, **kwargs).prefetch_related('probechannel_set')
class Probe(models.Model):
Client = models.ForeignKey('Client')
objects = ProbeManager()
class ProbeChannel(models.Model):
Probe = models.ForeignKey('Probe')
有没有办法避免这种情况?我读过 _base_managers 用于相关对象,但这里的 _base_manager 只是 models.Manager。我正在使用 django 1.11 和这个叫做 python 2.7.
的时髦新东西我仍然不确定这是否是所需的 Django 行为,但预取肯定会触发两次。我想出的避免 ProbeManager 预取被触发的答案很简单——避免使用这个管理器。 所以在 Probe class 我添加了
objects_without_prefetch = models.Manager()
然后使用预取对象 Prefetch('probe_set',Probe.objects_without_prefetch.all()) 而不是简单地使用调用其自己的预取的 'probe_set'。
无论如何感谢那些花时间思考这个问题并回答的人!