1

简单版:

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

一些细节:

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

它的形式很简单(过于简单的例子):

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

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

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

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

使用 django 模型接口会产生什么开销来解释这种显着的性能差异?

更新:

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 完成的。

4

1 回答 1

3

如果您对问题的更新中的两个代码段进行计时,那么是的,区别在于 django 将 DB 查询的结果编组为 700,000 个 python 对象(即,它调用了object.__init__()700,000 次)。

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

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

于 2013-08-01T02:53:59.070 回答