我正在生成项目之间的相似性矩阵,以便将其提供给Django中的推荐系统。 (一天结束时为n ^ 2。)
我遇到的问题是,无论我是否使用iterator()
,RAM仍然被占用。
我做这样的事情:
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()函数,但后来我相信是由数据库客户端缓存结果。
泄漏仍然存在,过一会儿我必须重新加载脚本。
我知道创建与元素一样多的迭代器看起来并不高效,因为那样我最终将所有元素都存储在内存中,你们会怎么做?
有什么想法吗?谢谢!
最佳答案
实际上,您的解决方案几乎可以。有一些建议:
不要deepcopy
queryset,无论如何切片它都会被克隆。
从数据库角度来看,切片效率低下(SQL中的偏移量较大),这意味着数据库需要准备很多行,然后只传递几行。
如果可以在表之间添加或删除任何内容,切片也不安全。
您可以使this thing适应您的情况。只需使用item_id
而不是pk
。它使用条件而不是偏移量,因此效率更高。
关于python - 在Django中计算大型数据集,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24152324/