我正在生成项目之间相似性的矩阵,以便将它提供给Django中的推荐系统。 (在一天结束时它是n ^ 2.)
我遇到的问题是,如果我使用iterator()
,我的内存仍然会被吸引。
我做这样的事情:
rated_apps_list = Rating.objects.values_list('item_id', flat=True).order_by('-item_id').distinct()
rated_apps_iter = MemorySavingQuerysetIterator(rated_apps_list[start:])
for app_above in rated_apps_iter:
rated_apps_below_iter = MemorySavingQuerysetIterator(rated_apps_list[i+1:])
for app_below in rated_apps_below_iter:
...
MemorySavingQuerySetIterator是:
class MemorySavingQuerysetIterator(object):
def __init__(self,queryset,max_obj_num=1000):
self._base_queryset = queryset
self._generator = self._setup()
self.max_obj_num = max_obj_num
def _setup(self):
for i in xrange(0,self._base_queryset.count(),self.max_obj_num):
# By making a copy of of the queryset and using that to actually access
# the objects we ensure that there are only `max_obj_num` objects in
# memory at any given time
smaller_queryset = copy.deepcopy(self._base_queryset)[i:i+self.max_obj_num]
#logger.debug('Grabbing next %s objects from DB' % self.max_obj_num)
for obj in smaller_queryset.iterator():
yield obj
def __iter__(self):
return self
def next(self):
return self._generator.next()
刚开始我只尝试使用.iterator()函数,但后来我相信数据库客户端正在缓存结果。 泄漏继续存在,我必须在一段时间后重新加载脚本。
我知道创建与元素一样多的迭代器看起来效率并不高,因为那样我最终会将所有元素都放在内存中,你们会怎么做呢?
有什么想法?谢谢!
答案 0 :(得分:1)
实际上,您的解决方案几乎没问题。建议很少:
deepcopy
查询集,无论如何都要克隆它。您可以根据自己的情况调整this thing。只需使用item_id
代替pk
即可。它使用条件而不是偏移,因此效率更高。