【问题标题】:Fetching queryset data one by one一个一个地获取查询集数据
【发布时间】:2015-12-06 08:08:41
【问题描述】:

我知道常规查询集或迭代器查询集方法会一次性评估并返回整个数据集。

例如,拿这个:

my_objects = MyObject.objects.all()
for rows in my_objects:            # Way 1
for rows in my_objects.iterator(): # Way 2

问题

在这两种方法中,所有行都是一次性获取的。在 djago 中是否有任何方法可以从数据库中一一获取查询集行。

为什么会有这个奇怪的要求

目前我的查询获取让我们说 n 行但有时我得到Python and Django OperationalError (2006, 'MySQL server has gone away')

为了解决这个问题,我目前正在使用一个奇怪的while 循环逻辑。所以想知道是否有任何 nativeinbuilt 方法或者是我的问题首先是合乎逻辑的! :)

【问题讨论】:

    标签: python django iteration django-queryset


    【解决方案1】:

    我想你正在寻找limit your query set

    引用以上链接:

    使用 Python 数组切片语法的子集将 QuerySet 限制为一定数量的结果。这相当于 SQL 的 LIMIT 和 OFFSET 子句。

    换句话说,如果你从一个计数开始,你可以循环并根据需要获取切片..

    cnt = MyObject.objects.count()
    start_point = 0
    inc = 5
    while start_point + inc < cnt:
        filtered = MyObject.objects.all()[start_point:inc]
        start_point += inc
    

    当然你可能需要更多地处理这个错误..

    【讨论】:

    • 我假设您已经研究过在这里解决实际问题,这当然是首选:)
    • 这绝对是我在挖掘时考虑过的一种方式,看起来很整洁。我想知道 django 本身是否还有其他 native 方式没有限制?至于实际问题,则与django版本有关,但由于整个项目都是基于它的,我对此无能为力.....
    • @NoobEditor - 我认为这几乎是原生的,因为这会修改您执行的查询。您仍将在数据库上执行多个查询,但一次只返回 N 个结果。另一种选择是查看您实际需要返回的内容并使用values 仅返回这些字段。 (另请注意,虽然在我的示例中我一次只获取 5 个,但我想你可以一次处理比这更多的)
    • 我同意...根据要求,这是我得到的最接近的。此外,它还具有灵活性,取决于要检索的查询大小和计数!!
    • @NoobEditor - 确实 :) 这个例子显然没有经过测试,所以如果你决定采用这种方法,你可能需要使用循环逻辑(我认为它可能会错过最后几行 atm) .
    【解决方案2】:

    逐行获取可能会更糟。您可能希望分批检索 1000 次等。我有 used this Django snippet(不是我的工作)成功地使用非常大的查询集。它不会占用内存,也不会出现连接消失的问题。

    这是来自该链接的 sn-p:

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

    【讨论】:

    【解决方案3】:

    要解决 (2006, 'MySQL server has gone away') 问题,您的方法不是那么合乎逻辑。如果您为每个条目点击数据库,它将增加查询的数量,随着应用程序使用量的增长,这本身会在未来产生问题。 我认为您应该在迭代结果的所有元素后关闭 mysql 连接,然后如果您尝试进行另一个查询,django 将创建一个新连接。

    from django.db import connection:
    connection.close()
    

    Refer this for more details

    【讨论】:

    • 问题是connection 在获取查询集时被转储......因此出现错误。所以即使我关闭并启动新连接,我也会再次遇到同样的问题。我试过connections.connection & is_usable 但没有帮助! :\
    猜你喜欢
    • 1970-01-01
    • 2018-05-11
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-04
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多