python - 从Django ORM中高效提取大量数据

标签 python django postgresql psycopg2

我有一个带有 PostgreSQL DB 的 Django 设置。 其中一个表包含大量数据(>1e9 行),我需要有效地迭代其中的一个大子集。

目前,当我尝试选择大量数据时,它会开始缓冲结果,并且我的计算机内存不足。 如果我在 QuerySet 上使用 .iterator() ,它就会挂起。 如果我尝试使用原始 SQL 和 fetchall(),它也会开始缓冲。

我相信 Django 对 PostgreSQL 使用 psycopg2,它有 cursor.itersize 参数,但是当我尝试在 Django 中将它与游标一起使用时,它不会执行任何操作。

我知道问题不在数据库端,因为我可以使用 psql 执行查询(使用 -A --variable="FETCH_COUNT=10000")它立即开始加载,不使用任何内存。

额外信息:

  • 该表有超过 10 列,但我只需要其中 2 列,因此如果可以仅获取选定的列以加快加载速度,那就太好了。

编辑:使用psycopg2服务器端光标似乎可以工作,但速度较慢且丑陋:How can I use server-side cursors with django and psycopg2?

编辑2:这是现在对我有用的代码,但非常丑陋:

def get_stuff():
    def fetch_from_server_cursor(cursor, cursor_name, fetch_size=10_000):
        while True:
            cursor.execute(f"FETCH {fetch_size} FROM {cursor_name}")
            chunk = cursor.fetchall()
            if not chunk:
                return
            yield from chunk

    with transaction.atomic(), connection.cursor() as cursor:
        cursor_name = "my_cursor"
        cursor.execute(
            f"""
            DECLARE {cursor_name} CURSOR FOR
            SELECT first_column, second_column
            FROM {MyModel.objects.model._meta.db_table}
            """
        )
        yield from fetch_from_server_cursor(cursor, cursor_name)

编辑 3:这是 Django 模型,注意:我在数据库中的表上使用 Timescale,它会自动在 TimeScaleDateTimeField 上创建索引:

class MyModel(models.Model):
    first_column = models.IntegerField()
    second_column = models.TimeScaleDateTimeField()
    third_column = models.URLField(null=True, blank=True)
    ...

    class Meta:
        ordering = ("second_column",)

最佳答案

The table has [more than] 10 columns, but I only need 2 of them, so if it is possible to only fetch selected for faster loading it would be nice.

您可以使用.only(…) [Django-doc]来做到这一点仅选择列的子集,例如:

for item in MyModel.objects.only('pk', '<i>other_column</i>').iterator():
    print((item.pk, item.<i>other_column</i>))

这将减少数据库和应用程序层之间的一些带宽。但无论如何,109 项在 Python 中通常不太可行。例如,如果我们简单地对此类范围内的项目进行求和 (sum(range(1000000000))),则需要约 14 秒,但这是一个非常简单的生成器。 Django 将为每条记录从数据库中读取内容,创建一个模型对象,并相应地设置字段,因此这很容易需要几分钟甚至几小时。

关于python - 从Django ORM中高效提取大量数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67544331/

相关文章:

python - CSS 不适用于 Django 支持的网站

python - psycopg2 在 centOS 上安装失败

到 Mayavi 的 Python 管道

python - 文件,剥离每一行并添加到字典中的键

python - 令人困惑的未缩进错误

python - 为什么我的训练损失在使用预先训练的权重训练 AlexNet 最后一层时会出现振荡?

python - 有时,Django 消息在请求之间重复(即,它们没有被清除)

json - 超出范围的浮点值与 Django 渲染不兼容 JSON

sql - 跨行聚合列

django - 我的 Django 应用程序中的默认数据库是只读的