1

シンプルバージョン:

Django の raw SQL が QuerySet インターフェースよりも効率的なのはなぜですか?

いくつかの詳細:

PostgreSQL データベースから ~ 700,000 (それ以上になる可能性があります) 行を返すクエリがあります。各行には、いくつかの double 値、いくつかの文字列、およびいくつかの整数が含まれています。したがって、適度に複雑なリターンです。

形式は単純です (単純化しすぎた例):

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()

「クエリ」は、クエリセットから生成された connection.queries コードの正確な文字列表現です。

更新 2:

タイミングはline_profiler、最初のクエリから返されたタプルのリストまでの時間の合計を使用して実行されます (両方のオプションでまったく同じ結果が返されます)。生のクエリがデータベースで直接かかる時間もテストしました(両方ともまったく同じです)。タイミングの不一致は、各メソッドを介して python から実行される場合です。

4

1 に答える 1

3

質問の更新で 2 つのコード セグメントの時間を測定した場合、はい、違いは、django が DB クエリの結果を 700,000 の Python オブジェクトにマーシャリングしているためです (つまり、object.__init__()700,000 回呼び出しています)。

クエリに生の SQL を使用しても問題はありません。これは、情報をどう処理するかに応じて、アドバイスされる可能性があるケースです。

そうは言っても....応答に700,000個のオブジェクトが必要ですか? 代わりに dict の 700,000 個の項目が実行されますか (生の SQL クエリが返すものです)? または、ページネーションまたはクエリ セット スライスを使用して、返される行を制限できますか?

于 2013-08-01T02:53:59.070 に答える