2

私は約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=  ...)

完全なクエリを評価しました。ページ付けされたクエリではありません。

4

1 に答える 1

3

djangoがページ付けを行う場合、標準のQuerySetスライスを使用して結果を取得します。これは、とを使用することを意味しLIMITますOFFSET

str()QuerySetの.query属性を呼び出すことにより、ORMが生成するSQLを表示できます。

    print MyModel.objects.all().query
    print MyModel.objects.all()[50:100].query

次に、sqliteにEXPLAINクエリを要求して、データベースが何をしようとしているのかを確認できます。インデックスのないフィールドで並べ替えていると思います。http://www.sqlite.org/lang_explain.htmlEXPLAIN QUERY PLANのsqliteドキュメントによると、どのインデックスが使用されたかがわかります

于 2010-11-01T19:14:48.413 に答える