在Django中计算大型数据集

时间:2014-06-10 23:12:25

标签: python mysql django

我正在生成项目之间相似性的矩阵,以便将它提供给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()函数,但后来我相信数据库客户端正在缓存结果。 泄漏继续存在,我必须在一段时间后重新加载脚本。

我知道创建与元素一样多的迭代器看起来效率并不高,因为那样我最终会将所有元素都放在内存中,你们会怎么做呢?

有什么想法?谢谢!

1 个答案:

答案 0 :(得分:1)

实际上,您的解决方案几乎没问题。建议很少:

  1. 不要deepcopy查询集,无论如何都要克隆它。
  2. 从数据库角度来看切片效率很低(sql中的大偏移量),这意味着数据库需要准备很多行,然后只传递几行。
  3. 如果可以在表格之间添加或删除任何内容,则切片也是不安全的。
  4. 您可以根据自己的情况调整this thing。只需使用item_id代替pk即可。它使用条件而不是偏移,因此效率更高。