一个接一个地获取queryset数据
Fetching queryset data one by one
我知道常规查询集或迭代器查询集方法评估并 returns 一次性完成整个数据集。
例如,拿这个:
my_objects = MyObject.objects.all()
for rows in my_objects: # Way 1
for rows in my_objects.iterator(): # Way 2
问题
在这两种方法中,所有的行都是在一个单一的go.Is中获取的,在 djago 中有任何方法可以从数据库中一个一个地获取查询集行。
为什么这个奇怪的要求
目前我的查询获取了 n 行,但有时我得到 Python and Django OperationalError (2006, 'MySQL server has gone away')。
所以为了解决这个问题,我目前正在使用一个奇怪的 while
循环 logic.So 想知道是否有任何 native 或 inbuilt 方法或者我的问题首先是合乎逻辑的!! :)
我想你正在寻找 limit your query set。
引自上文link:
Use a subset of Python’s array-slicing syntax to limit your QuerySet to a certain number of results. This is the equivalent of SQL’s LIMIT and OFFSET clauses.
换句话说,如果您从计数开始,然后可以循环并根据需要进行切片..
cnt = MyObject.objects.count()
start_point = 0
inc = 5
while start_point + inc < cnt:
filtered = MyObject.objects.all()[start_point:inc]
start_point += inc
当然你可能需要更多的错误处理..
逐行获取可能更糟糕。您可能希望分批检索 1000 秒等。我已经 used this Django snippet(不是我的工作)成功地使用了非常大的查询集。它不会占用内存,也不会因连接中断而出现问题。
这是 link 的片段:
import gc
def queryset_iterator(queryset, chunksize=1000):
'''''
Iterate over a Django Queryset ordered by the primary key
This method loads a maximum of chunksize (default: 1000) rows in it's
memory at the same time while django normally would load all rows in it's
memory. Using the iterator() method only causes it to not preload all the
classes.
Note that the implementation of the iterator does not support ordered query sets.
'''
pk = 0
last_pk = queryset.order_by('-pk')[0].pk
queryset = queryset.order_by('pk')
while pk < last_pk:
for row in queryset.filter(pk__gt=pk)[:chunksize]:
pk = row.pk
yield row
gc.collect()
要解决(2006, 'MySQL server has gone away')问题,你的做法不合逻辑。如果您将为每个条目访问数据库,它将增加查询的数量,这本身会在未来随着您的应用程序使用量的增长而产生问题。
我认为你应该在迭代结果的所有元素后关闭 mysql 连接,然后如果你尝试进行另一个查询,django 将创建一个新连接。
from django.db import connection:
connection.close()
我知道常规查询集或迭代器查询集方法评估并 returns 一次性完成整个数据集。
例如,拿这个:
my_objects = MyObject.objects.all()
for rows in my_objects: # Way 1
for rows in my_objects.iterator(): # Way 2
问题
在这两种方法中,所有的行都是在一个单一的go.Is中获取的,在 djago 中有任何方法可以从数据库中一个一个地获取查询集行。
为什么这个奇怪的要求
目前我的查询获取了 n 行,但有时我得到 Python and Django OperationalError (2006, 'MySQL server has gone away')。
所以为了解决这个问题,我目前正在使用一个奇怪的 while
循环 logic.So 想知道是否有任何 native 或 inbuilt 方法或者我的问题首先是合乎逻辑的!! :)
我想你正在寻找 limit your query set。
引自上文link:
Use a subset of Python’s array-slicing syntax to limit your QuerySet to a certain number of results. This is the equivalent of SQL’s LIMIT and OFFSET clauses.
换句话说,如果您从计数开始,然后可以循环并根据需要进行切片..
cnt = MyObject.objects.count()
start_point = 0
inc = 5
while start_point + inc < cnt:
filtered = MyObject.objects.all()[start_point:inc]
start_point += inc
当然你可能需要更多的错误处理..
逐行获取可能更糟糕。您可能希望分批检索 1000 秒等。我已经 used this Django snippet(不是我的工作)成功地使用了非常大的查询集。它不会占用内存,也不会因连接中断而出现问题。
这是 link 的片段:
import gc
def queryset_iterator(queryset, chunksize=1000):
'''''
Iterate over a Django Queryset ordered by the primary key
This method loads a maximum of chunksize (default: 1000) rows in it's
memory at the same time while django normally would load all rows in it's
memory. Using the iterator() method only causes it to not preload all the
classes.
Note that the implementation of the iterator does not support ordered query sets.
'''
pk = 0
last_pk = queryset.order_by('-pk')[0].pk
queryset = queryset.order_by('pk')
while pk < last_pk:
for row in queryset.filter(pk__gt=pk)[:chunksize]:
pk = row.pk
yield row
gc.collect()
要解决(2006, 'MySQL server has gone away')问题,你的做法不合逻辑。如果您将为每个条目访问数据库,它将增加查询的数量,这本身会在未来随着您的应用程序使用量的增长而产生问题。 我认为你应该在迭代结果的所有元素后关闭 mysql 连接,然后如果你尝试进行另一个查询,django 将创建一个新连接。
from django.db import connection:
connection.close()