简单版本
为什么Django中的原始SQL比QuerySet接口更有效?
详情:
我有一个从PostgreSQL数据库返回约700,000(可能更多)行的查询。每行包含一些双精度值,一些字符串和一些整数。所以回报过于复杂。
形式简单(简化示例):
SELECT (a,b,c) FROM table WHERE d=something AND e=somethings ORDER BY a;
当我使用模型接口和.filter()来进行查询时,执行查询大约需要30秒。这是不可接受的。
我尝试过使用所有建议的方法。 (迭代器,内存高效迭代器等......)
但是,当我在Django中使用connection.cursor
...和fetchall
执行完全相同的查询时,查询将下降到大约5秒来执行。
使用django模型界面产生的开销会产生这种显着的性能差异吗?
更新
Django QuerySet代码:
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代码的EXACT字符串表示。
更新2:
使用line_profiler
完成计时并获取从初始查询到返回的元组列表的时间总和(两个选项完全相同的返回)。我还测试了原始查询直接在数据库上进行的时间(两者完全相同)。时间上的差异是从python通过每种方法完成的。
答案 0 :(得分:3)
如果你把更新中的两个代码段计时到你的问题,那么是,差异是因为django正在将数据库查询的结果编组为700,000个python对象(即,它调用object.__init__()
700,000次)
使用原始sql进行查询没有任何问题。这种情况可能会被建议,具体取决于您对信息的处理方式。
那说......你在响应中需要700,000个对象吗?一个字典中的700,000个项目会改为(原始的sql查询返回的是什么)?或者,您可以使用分页或查询集切片来限制返回的行吗?