django - 为什么通过 Django QuerySet 进行查询比仅在 Django 中使用游标慢得多?

标签 django postgresql django-queryset

简单版本:

为什么 Django 中的原始 SQL 比 QuerySet 接口(interface)更高效?

一些细节:

我有一个查询从 PostgreSQL 数据库返回大约 700,000(可能更多)行。每行包含一些 double 值、一些字符串和一些整数。所以一个适度复杂的返回。

形式简单(过度简化的示例):

SELECT (a,b,c) FROM table WHERE d=something AND e=somethings ORDER BY a;

当我使用模型接口(interface)和 .filter() 进行查询时,查询的执行大约需要 30 秒。这是 Not Acceptable 。

我已尝试使用所有建议的方法。 (迭代器、内存高效迭代器等...)

但是,当我在 Django 中使用 connection.cursor ... 和 fetchall 执行完全相同的查询时,查询的执行时间下降到大约 5 秒。

使用 django 模型接口(interface)产生的开销是什么导致了这种显着的性能差异?

更新:

Django 查询集代码:

c_layer_points = models.layer_points.objects.filter(location_id__location_name=region,season_id__season_name=season,line_path_id=c_line_path.pk,radar_id=c_radar.pk,gps_time__gte=start_gps,gps_time__lte=stop_gps).order_by('gps_time').values_list('gps_time','twtt','pick_type','quality','layer_id')

快速版本中完全相同的查询:

# OPEN a cursor
cursor = connection.cursor()

# EXECUTE the query
cursor.execute(query)
transaction.commit_unless_managed()

# FETCH all the rows
rows = cursor.fetchall()

其中“query”是从 Queryset 生成的 connection.queries 代码的精确字符串表示。

更新 2:

计时是使用 line_profiler 完成的,并计算从初始查询到返回的元组列表的时间总和(两个选项的返回完全相同)。我还测试了原始查询直接在数据库上花费的时间(两者完全相同)。时间上的差异是通过每种方法从 python 完成的。

最佳答案

如果您在问题的更新中对两个代码段进行了计时,那么是的,不同之处在于 django 将数据库查询的结果编码为 700,000 个 python 对象(即调用 object.__init__() 700,000 次)。

使用原始 sql 进行查询没有任何问题。在这种情况下,可能会建议这样做,具体取决于您对信息的处理方式。

也就是说....您需要在响应中包含 700,000 个对象吗?字典中的 700,000 个项目会代替吗(这就是原始 sql 查询返回的内容)?或者您可以通过分页或查询集切片来限制返回的行数吗?

关于django - 为什么通过 Django QuerySet 进行查询比仅在 Django 中使用游标慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17602756/

相关文章:

mysql - 在 Django 中,我可以在检索查询集之前在序言中设置变量吗?

Python calendar.month_name 如何跳过 0-index

django - IntegrityError 重复键值违反唯一约束 - django/postgres

postgresql - GORM 不创建 ForeignKey 列

python - Django 原始查询 - 使用点符号遍历相关模型的字段

sql - django 查询集按小时、分钟和秒排序

mysql - 带有额外选择的 Django 查询集计数

python - 尝试 Django 迁移会生成错误 : "Unknown field(s) (groups) specified for User"

django - 如何在 Django 序列化器中使用主键

postgresql - Slick 2.0 - 更新两列或更多列