私は約3900エントリの単純なデータベースを持っており、データベース内のデータを参照するためにdjango-pagination(paginate_byを介して)でジェネリックビュー(django.views.generic.list_detail.object_list)を使用していますが、一部のクエリは非常に遅いです。
奇妙なことに、1ページに50個のオブジェクトしか表示されないにもかかわらず、レンダリング時間は選択されたオブジェクトの数にほぼ比例します(オブジェクトの並べ替えは行いません)。たとえば、〜3900、〜1800、〜900、〜54の選択されたオブジェクトでクエリを実行すると、それぞれ〜8500ミリ秒、〜4000ミリ秒、〜2500ミリ秒、〜800ミリ秒のCPU時間がかかります(django-debug-toolbarを使用) SQLには約50ミリ秒、約40ミリ秒、約35ミリ秒、約30ミリ秒しかかかりませんでしたが、すべてのページに正確に50個のオブジェクトがありました。djangoの最適化ページで提案されているように、select_relatedを使用してSQLクエリの数を最小限に抑えました。
プロファイリングミドルウェアを使用すると、長いクエリにかかる時間の大部分は、dbの処理に費やされます。
735924 function calls (702255 primitive calls) in 11.950 CPU seconds
Ordered by: internal time, call count
ncalls tottime percall cumtime percall filename:lineno(function)
35546/3976 4.118 0.000 9.585 0.002 /usr/local/lib/python2.6/dist-packages/django/db/models/query.py:1120(get_cached_row)
30174 3.589 0.000 3.991 0.000 /usr/local/lib/python2.6/dist-packages/django/db/models/base.py:250(__init__)
---- By file ----
tottime
47.0% 3.669 /usr/local/lib/python2.6/dist-packages/django/db/models/base.py
7.7% 0.601 /usr/local/lib/python2.6/dist-packages/django/db/models/options.py
6.8% 0.531 /usr/local/lib/python2.6/dist-packages/django/db/models/query_utils.py
6.6% 0.519 /usr/local/lib/python2.6/dist-packages/django/db/backends/sqlite3/base.py
6.4% 0.496 /usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py
5.0% 0.387 /usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py
3.1% 0.244 /usr/local/lib/python2.6/dist-packages/django/db/backends/util.py
2.9% 0.225 /usr/local/lib/python2.6/dist-packages/django/db/backends/__init__.py
2.7% 0.213 /usr/local/lib/python2.6/dist-packages/django/db/models/query.py
2.2% 0.171 /usr/local/lib/python2.6/dist-packages/django/dispatch/dispatcher.py
1.7% 0.136 /usr/local/lib/python2.6/dist-packages/django/template/__init__.py
1.7% 0.131 /usr/local/lib/python2.6/dist-packages/django/utils/datastructures.py
1.1% 0.088 /usr/lib/python2.6/posixpath.py
0.8% 0.066 /usr/local/lib/python2.6/dist-packages/django/db/utils.py
...
---- By group ---
tottime
89.5% 6.988 /usr/local/lib/python2.6/dist-packages/django/db
3.6% 0.279 /usr/local/lib/python2.6/dist-packages/django/utils
...
選択したエントリの数に応じてSQLクエリを拡張できる理由を理解できます。ただし、CPU時間の残りの部分がとにかく影響を受ける必要がある理由がわかりません。これは非常に直感に反しており、誰かが私を助けてくれるデバッグ/プロファイリングのヒントがあるかどうか疑問に思っていました。
django-1.2.3をsqlite、python2.6、apache2-preforkで使用します(ただし、mpm-workerに切り替えても大幅な変更はありませんでした)。ヒント/コツをいただければ幸いです。メモリ使用量も要因ではないようで(マシンには2Gb RAMがあり、空き容量は300Mbのみを使用している(さらに600Mbのキャッシュ))、データベースはマシンと同じサーバー上にあります。
私の間違いを見つけました。私は自分の間違いを見つけました。元のクエリセットの長さをチェックして、長さが1であるかどうかを確認しました(長さが1の場合はobject_detailに移動しました)。これにより、完全なクエリセット(django-debug-toolbarによると5msしかかかりません)が評価されましたが、すべてが大幅に遅くなりました。
基本的に次のような愚かなものがありました:
if len(queryset) == 1:
return HttpResponseRedirect( fwd to object_detail url ...)
return object_list(request, queryset=queryset, paginate_by= ...)
完全なクエリを評価しました。ページ付けされたクエリではありません。