查询集什么时候使用它的 _result_cache,而不是访问数据库?
When does the queryset use its _result_cache, not hitting the database?
我对查询集使用其 _result_cache
或直接访问数据库的时间感到困惑。
例如(在pythonshell):
user = User.objects.all() # User is one of my models
print(user) # show data in database (hitting the database)
print(user._result_cache) # output is None
len(user) # output is a nonzero number
print(user._result_cache) # this time, output is not None
那么,我的问题是:
- 为什么
_result_cache
在访问数据库后是None
?
- 是否对查询集求值意味着
_result_cache
不是 None
?
- 查询集什么时候使用它的
_result_cache
,而不是访问数据库?
对此行为有一个解释:
当您使用 User.objects.all() 时,数据库不是 hit.When 您不遍历查询集,当您调用 len 时 _result_cache 始终是 None.But () function.The 迭代将通过查询集完成,数据库将被命中,结果输出也将为该查询集设置 result_cahce。
这是 Django 的 len() 函数的源代码:
def __len__(self):
# Since __len__ is called quite frequently (for example, as part of
# list(qs), we make some effort here to be as efficient as possible
# whilst not messing up any existing iterators against the QuerySet.
if self._result_cache is None:
if self._iter:
self._result_cache = list(self._iter)
else:
self._result_cache = list(self.iterator())
elif self._iter:
self._result_cache.extend(self._iter)
return len(self._result_cache)
希望这能澄清您的所有问题。谢谢
只要 complete 查询集被评估,查询集就会将其数据缓存在 self._result_cache
中。这包括遍历查询集,调用 bool()
、len()
或 list()
,或对查询集进行酸洗。
print()
函数间接调用查询集上的 repr()
。 repr()
将评估查询集以将数据包含在字符串表示中,但不会评估 complete 查询集。相反,它将 get a slice 查询集并在表示中使用它。当您只需要一个简单的字符串表示时,这可以防止大量查询。由于只评估一个切片,因此不会缓存结果。
当缓存被填满时,每个不创建新查询集对象的方法都将使用缓存而不是进行新查询。在您的具体示例中,如果您切换 print()
和 len()
语句,您的查询集只会访问数据库一次:
user = User.objects.all()
len(user) # complete queryset is evaluated
print(user._result_cache) # cache is filled
print(user) # slicing an evaluated queryset will not hit the database
print(user._result_cache)
我对查询集使用其 _result_cache
或直接访问数据库的时间感到困惑。
例如(在pythonshell):
user = User.objects.all() # User is one of my models
print(user) # show data in database (hitting the database)
print(user._result_cache) # output is None
len(user) # output is a nonzero number
print(user._result_cache) # this time, output is not None
那么,我的问题是:
- 为什么
_result_cache
在访问数据库后是None
? - 是否对查询集求值意味着
_result_cache
不是None
? - 查询集什么时候使用它的
_result_cache
,而不是访问数据库?
对此行为有一个解释:
当您使用 User.objects.all() 时,数据库不是 hit.When 您不遍历查询集,当您调用 len 时 _result_cache 始终是 None.But () function.The 迭代将通过查询集完成,数据库将被命中,结果输出也将为该查询集设置 result_cahce。 这是 Django 的 len() 函数的源代码:
def __len__(self):
# Since __len__ is called quite frequently (for example, as part of
# list(qs), we make some effort here to be as efficient as possible
# whilst not messing up any existing iterators against the QuerySet.
if self._result_cache is None:
if self._iter:
self._result_cache = list(self._iter)
else:
self._result_cache = list(self.iterator())
elif self._iter:
self._result_cache.extend(self._iter)
return len(self._result_cache)
希望这能澄清您的所有问题。谢谢
只要 complete 查询集被评估,查询集就会将其数据缓存在 self._result_cache
中。这包括遍历查询集,调用 bool()
、len()
或 list()
,或对查询集进行酸洗。
print()
函数间接调用查询集上的 repr()
。 repr()
将评估查询集以将数据包含在字符串表示中,但不会评估 complete 查询集。相反,它将 get a slice 查询集并在表示中使用它。当您只需要一个简单的字符串表示时,这可以防止大量查询。由于只评估一个切片,因此不会缓存结果。
当缓存被填满时,每个不创建新查询集对象的方法都将使用缓存而不是进行新查询。在您的具体示例中,如果您切换 print()
和 len()
语句,您的查询集只会访问数据库一次:
user = User.objects.all()
len(user) # complete queryset is evaluated
print(user._result_cache) # cache is filled
print(user) # slicing an evaluated queryset will not hit the database
print(user._result_cache)