【问题标题】:Reducing queries for manytomany models in django减少 django 中多对多模型的查询
【发布时间】:2010-12-14 06:02:27
【问题描述】:

编辑: 事实证明,真正的问题是 - 我如何让 select_related 遵循我定义的 m2m 关系?这些是对我的系统征税的那些。有什么想法吗?

我的 django 应用程序有两个类。第一个(Item 类)描述了一个项目以及一些返回有关该项目的信息的函数。第二个类(Itemlist 类)获取这些项目的列表,然后对它们进行一些处理以返回不同的值。我遇到的问题是从 Itemlist 返回项目列表需要大量查询,我不确定它们来自哪里。

class Item(models.Model):

# for archiving purposes
archive_id  = models.IntegerField()
users       = models.ManyToManyField(User, through='User_item_rel',
                                     related_name='users_set')

# for many to one relationship (tags)
tag         = models.ForeignKey(Tag)
sub_tag     = models.CharField(default='',max_length=40)

name        = models.CharField(max_length=40)
purch_date  = models.DateField(default=datetime.datetime.now())
date_edited = models.DateTimeField(auto_now_add=True)
price       = models.DecimalField(max_digits=6, decimal_places=2)
buyer       = models.ManyToManyField(User, through='Buyer_item_rel',
                                     related_name='buyers_set')
comments    = models.CharField(default='',max_length=400)
house_id    = models.IntegerField()

class Meta:
    ordering = ['-purch_date']

def shortDisplayBuyers(self):
    if len(self.buyer_item_rel_set.all()) != 1:
        return "multiple buyers"
    else:
        return self.buyer_item_rel_set.all()[0].buyer.name
def listBuyers(self):
    return self.buyer_item_rel_set.all()

def listUsers(self):
    return self.user_item_rel_set.all()

def tag_name(self):
    return self.tag

def sub_tag_name(self):
    return self.sub_tag

def __unicode__(self):
    return self.name

第二类:

class Item_list:

def __init__(self, list = None, house_id = None, user_id = None,
             archive_id = None, houseMode = 0):
    self.list = list
    self.house_id = house_id
    self.uid = int(user_id)
    self.archive_id = archive_id
    self.gen_balancing_transactions()
    self.houseMode = houseMode

def ret_list(self):
    return self.list

因此,在我用大量项目构建 Itemlist 后,Itemlist.ret_list() 最多需要 800 次查询来处理 25 个项目。我该怎么做才能解决这个问题?

【问题讨论】:

  • len(self.buyer_item_rel_set.all()) 将其更改为使用 count()。很痛(性能)。

标签: django


【解决方案1】:

尝试使用 select_related

根据我问过的问题here

【讨论】:

  • 所以如果我有一个使用 select_related() 的查询集,是否根据相关字段过滤该查询集也不会触及数据库?
  • 我对内部结构不是特别熟悉,但我相信它会加载并缓存查询集的相关对象,并因此运行更少的查询。虽然,如果您在已经调用 select_related 之后过滤相关对象,我想它必须重新查询数据库是有道理的。试试看吧。
【解决方案2】:

Dan 告诉你使用select_related 是对的。

select_related 可以读到here

它的作用是为查询集中的主要对象以及select_related 子句中指定的模型或字段返回相同的查询数据。

所以,而不是像这样的查询:

select * from item

每次访问 item_list 对象之一时,都会执行几个这样的查询:

select * from item_list where item_id = <one of the items for the query above>

ORM 将生成如下查询:

select item.*, item_list.* 
  from item a join item_list b
 where item a.id = b.item_id

换句话说:它会为所有数据访问数据库一次。

【讨论】:

    【解决方案3】:

    您可能想使用prefetch_related

    与 select_related 类似,但可以处理 selected_related 不能处理的关系。连接发生在 python 中,但我发现它比大量查询更有效。

    Related reading on the subject

    【讨论】:

      猜你喜欢
      • 2014-02-07
      • 2013-05-17
      • 2014-05-27
      • 2018-02-09
      • 2021-04-12
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 2017-04-21
      相关资源
      最近更新 更多