python - 从 Django ORM 中高效提取大量数据
问题描述
我有一个带有 PostgreSQL DB 的 Django 设置。其中一个表包含大量数据(>1e9 行),我需要有效地迭代其中的一个大子集。
目前,当我尝试选择大量数据时,它开始缓冲结果并且我的计算机内存不足。如果我.iterator()
在 QuerySet 上使用,它就会挂起。如果我尝试使用原始 SQL,fetchall()
它也会开始缓冲。
我相信 Djangopsycopg2
用于具有cursor.itersize
参数的 PostgreSQL,但是当我尝试在 Django 中将其与光标一起使用时,它什么也没做。
我知道问题不在数据库端,因为我可以使用psql
(with -A --variable="FETCH_COUNT=10000"
) 执行查询,并且它会立即开始加载而不使用任何内存。
额外信息:
- 该表有 >10 列,但我只需要其中的 2 列,因此如果可以只获取选定的以更快加载,那就太好了。
编辑:使用psycopg2
服务器端游标似乎可行,但速度较慢且丑陋:如何将服务器端游标与 django 和 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 模型,注意我在 DB 的表上使用 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",)
解决方案
该表有[多于] 10 列,但我只需要其中的 2 列,因此如果可以仅获取选定的以更快加载,那就太好了。
您可以使用.only(…)
[Django-doc]执行此操作,以仅选择列的子集,例如:
for item in MyModel.objects.only('pk', 'other_column').iterator():
print((item.pk, item.other_column))
这将减少数据库和应用层之间的一些带宽。但无论如何,10 9项在 Python 中通常是不可行的。例如,如果我们简单地将此类范围 ( sum(range(1000000000))
) 的项目相加,将需要 ≈ 14 秒,但这是一个非常简单的生成器。Django 将为每条记录从数据库中读取内容,创建一个模型对象,并相应地设置字段,因此这很容易花费几分钟甚至几小时。
推荐阅读
- reactjs - 为什么反应wai-aria不在camelCase中?
- css - 是否可以用 CSS 中的图像替换 HTML 图像?
- python - Finding day of the week for a datetime64
- latex - Evaluate a function and assign to a constant to use as tick markin Tikz/pgfplots
- c# - Unity 一个一个或一个块地实例化预制件?(性能问题)
- file - 在 Golang 中的文件之间附加
- azure-pipelines - 找不到与模式匹配的测试程序集:**\*Test*.dll,!**\*TestAdapter.dll,!**\obj\**
- php - php 变量随处可用
- php - 生成具有关系的种子数据
- r - Linear interpolation for missing data in R