У меня есть простая база данных с около 3900 записей, и я использую общий вид (django.views.generic.list_detail.object_list) с его django-pagination (через paginate_by) для просмотра данных в базе данных, но некоторые запросы очень медленные.Django Paginate CPU Время масштабирования с количеством выделенных объектов, не отображаемых объектов
Странно то, что, несмотря на то, что на странице показано всего 50 объектов, время рендеринга примерно линейно масштабируется с количеством объектов (и я не сортирую объекты). Например, если я делаю запрос с ~ 3900, ~ 1800, ~ 900, ~ 54 выбранных объектов, он соответственно принимает ~ 8500 мс, ~ 4000 мс, ~ 2500 мс, ~ 800 мс времени процессора (с помощью панели инструментов django-debug-toolbar) в то время как SQL занял ~ 50 мс, ~ 40 мс, ~ 35 мс, ~ 30 мс, снова, пока на всех страницах было ровно 50 объектов. Я минимизировал количество SQL-запросов, используя select_related, как предложено в django optimization page.
Использование profiling middleware подавляющее большинство времени на длинных запросов тратится делать дб материал:
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 запрос может масштабироваться с числом выбранных записей. Тем не менее, я не понимаю, почему остальное время процессора должно быть в любом случае затронуто. Это очень противоречиво, и мне было интересно, есть ли какие-нибудь советы по отладке/профилированию, с которыми кто-то мог бы мне помочь.
Использование django-1.2.3 с sqlite, python2.6, apache2-prefork (хотя переход на mpm-worker существенно не изменил ситуацию). Любые советы/трюки будут очень признательны. Использование памяти, по-видимому, не является фактором (машина имеет 2 ГБ оперативной памяти, а бесплатно говорит только с использованием только 300 МБ (дополнительно 600 МБ кеша)), а база данных находится на том же сервере, что и машина.
Обнаружили ошибку. Я нашел свою ошибку. Я проверил длину исходного запроса, чтобы увидеть, была ли длина 1 (а затем перешла к object_detail, если да). Это привело к оценке полного набора запросов (который по-прежнему занимал только 5 мс в соответствии с панелью django-debug-toolbar), но значительно замедлил все.
В основном что-то глупое, как:
if len(queryset) == 1:
return HttpResponseRedirect(fwd to object_detail url ...)
return object_list(request, queryset=queryset, paginate_by= ...)
, который оценивается полный запрос; а не постраничный запрос.
У вас есть индексы, установленные в вашей базе данных sqlite? В противном случае sqlite может выполнять линейное сканирование для фильтрации или сортировки. –
У меня нет указателей, настроенных на данный момент; но я тоже не сортирую результаты, и у меня создается впечатление, что панель django-debug-toolbar вызывает SQL-запросы. Поэтому, если SQL-запрос составляет 50 мс для выбора 1-50 из ~ 3900 объектов и ~ 30 мс для выбора 1-50 из ~ 54 объектов, разница в процессорном времени должна составлять только 20 мс, а не текущая разница 7800 мс , –