我正在使用Django 1.9.10:
我有一个名为Details
的模型,其unique_id
列已被编入索引:
try:
detail = Detail.objects.get(unique_id=UUID)
except MultipleObjectsReturned as m:
logger.error("uuid {} returned multiple objects - {}".format(UUID, str(m)))
由于代码UUID=None
出现了一些错误,导致MultipleObjectsReturned
出现错误。但是我们注意到几乎2 GB的内存正在耗尽,而且它正在大大减慢系统速度。
在错误日志中打印str(m)时,我们发现以下错误
MultipleObjectsReturned:get()返回多个详细信息 - 它返回451424!
我的问题是为什么Django只是为了引发错误而在内存中获取如此多的数据? Django可以获取计数吗?
我知道我可以使用filter()来解决这个问题,但我对此感到惊讶,并想了解为什么django会这样做?
答案 0 :(得分:3)
因为这是在内部完成的:
def get(self, *args, **kwargs):
"""
Perform the query and return a single object matching the given
keyword arguments.
"""
clone = self.filter(*args, **kwargs) # calling `filter()` inside
if self.query.can_filter() and not self.query.distinct_fields:
clone = clone.order_by()
num = len(clone)
if num == 1:
return clone._result_cache[0]
if not num:
raise self.model.DoesNotExist(
"%s matching query does not exist." %
self.model._meta.object_name
)
raise self.model.MultipleObjectsReturned(
"get() returned more than one %s -- it returned %s!" %
(self.model._meta.object_name, num)
)
查看完整的来源here。
我想你想知道为什么它不能只取这个数字?因为它会向数据库发出两个请求,而不是一个。一个获取计数的请求和一个获取数据的请求。
你怎么解决?您可以更改应用程序逻辑以避免这种情况。断言UUID
不是None
。或者在进行实际查询之前获取count
。
关于get
的文档:https://docs.djangoproject.com/en/dev/topics/db/queries/#retrieving-a-single-object-with-get
答案 1 :(得分:1)
因为你知道你不应该得到多个对象时使用.get。
如果在返回451424项目的情况下选择使用它而不是它的设计目的。
答案 2 :(得分:0)
因为您在数据库中有多个具有相同ID的人。
将您的查询重写为:Detail.objects.filter(unique_id=UUID)