我有一个包含大约 3900 个条目的简单数据库,并且正在使用带有 django-pagination(通过 paginate_by)的通用视图(django.views.generic.list_detail.object_list)来浏览数据库中的数据,但是有些查询非常慢.
奇怪的是,尽管每页只显示 50 个对象,但渲染时间与选择的对象数量大致呈线性关系(而且我没有对对象进行任何排序)。例如,如果我使用 ~3900、~1800、~900、~54 个选定对象进行查询,则分别需要 ~8500 ms、~4000 ms、~2500 ms、~800 ms 的 CPU 时间(使用 django-debug-toolbar)而 SQL 只用了 ~50 毫秒、~40 毫秒、~35 毫秒、~30 毫秒,而所有页面正好有 50 个对象。我已经按照django 优化页面中的建议使用 select_related 最小化了 SQL 查询的数量。
使用profiling 中间件进行长查询的大部分时间都花在做 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,free 说只使用 300Mb(另外还有 600Mb 的缓存)),并且数据库与机器位于同一台服务器上。
发现我的错误。我发现了我的错误。我检查了原始查询集的长度,看它是否为长度 1(如果是,则转到 object_detail)。这导致评估完整的查询集(根据 django-debug-toolbar 仍然只需要 5 毫秒),但显着减慢了一切。
基本上有一些愚蠢的东西:
if len(queryset) == 1:
return HttpResponseRedirect( fwd to object_detail url ...)
return object_list(request, queryset=queryset, paginate_by= ...)
它评估了完整的查询;不是分页查询。