2015-10-20 74 views
0

我正在与同事讨论关于通过Django ORM迭代大型表的问题。到现在为止我一直在使用一个queryset_iterator的实现为在这里看到:使用Django's Paginator并传递查询集成queryset_iterator和Django Paginator之间的差异

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() 

我的同事建议。看起来类似的工作会完成,唯一的区别是Paginator不会进行任何垃圾收集调用。

任何人都可以阐明两者之间的区别吗?有没有?

回答

2

这里的实现与Paginator完全不同,几乎没有相似之处。

你的类遍历整个查询集,每次请求chunksize项,每个块都是一个单独的查询。它只能用于无序查询,因为它自己执行order_by调用。

Paginator不会这样做。它不是遍历整个查询集,而是从完整的qs返回单个页面,它使用切片运算符(映射到LIMIT/OFFSET)对单个查询进行处理。

另外,我不确定你认为在这里调用gc.collect会做什么。垃圾收集器是主存储器管理系统的附件,它是引用计数。它仅用于清除循环引用,并且没有理由相信在此创建任何内容。