Скорость доступа к базе данных Django зависит от хоста, используемого в запросе

У меня проблемы с производительностью/скоростью в приложении Python/Django/Postgres. В частности, скорость запросов к базе данных (через ORM Django), похоже, связана с именем хоста, используемым в запросе к django. В примерах, которые я использую, используется либо localhost, либо имя хоста виртуальной машины (dev.virtual). При использовании имени хоста производительность хорошая, но при использовании localhost наблюдается значительное замедление (порядка десятков раз).

Я создал очень базовое представление, чтобы проверить это:

def generate_load_view(request, resource):

    length = int(request.GET.get("length"))
    length = 2 ** length

    iterations = int(request.GET.get("iterations"))
    iterations = 10 ** iterations

    if resource == "compute":
        load_generator = generate_compute_load

    elif resource == "memory":
        load_generator = generate_memory_load

    elif resource == "database":
        load_generator = generate_database_load

    else:
        raise Http404()

    t_start = time.monotonic()
    load_generator(length=length, iterations=iterations)
    t_end = time.monotonic()
    t_elapsed = t_end - t_start

    response = {"time": t_elapsed}
    return Response(response)

def generate_database_load(length, iterations):


    model = django.contrib.contenttypes.models.ContentType

    pks = model.objects.values_list("pk", flat=True)
    for _ in range(iterations):
        random_pk = random.choice(pks)
        random_obj = model.objects.get(pk=random_pk)

Я использую объект django ContentType из удобства.

<<<База данных (PostgreSQL) работает в контейнере docker на той же машине. Я использовал как сервер разработки django (через

), так и сервер manage.py без заметных изменений.gunicorn

Повторюсь, если я делаю запрос к http://localhost/generate_load/, он работает медленно, но если я делаю запрос (к тому же запущенному приложению, т.е. приложение не перенастраивается и даже не перезапускается) к http://dev.virtual/generate_load/, он работает значительно быстрее. В обоих случаях запросы делаются с одной и той же виртуальной машины (т.е. с той же машины, на которой запущены приложение django и БД).

Даже при извлечении одного объекта БД наблюдается большая пропорциональная разница, которая, похоже, увеличивается с количеством извлекаемых объектов.

В моих тестах имя хоста рандомизируется (например, при выполнении 10 запросов к каждому, последовательность случайна, а не все сначала одно, потом другое).

Похоже, что замена 127.0.0.1 на localhost не меняет ситуацию, поэтому я не думаю, что это связано с проблемами разрешения имени localhost.

Я пробовал изменить строку подключения к БД, чтобы использовать альтернативные имена хостов для БД (например, localhost и dev.virtual), а также пробовал изменить SITE_DOMAIN приложения django, но это ничего не изменило.

Я буду великолепно признателен за любую помощь в понимании и разрешении этой проблемы.

Самая удобная вещь, которая может изменить поведение в проекте Django в зависимости от IP-адреса - это панель инструментов отладки Django.

В документации (Performance considerations) вы можете прочитать:

Панель инструментов отладки разработана таким образом, чтобы вносить как можно меньше накладных расходов в процессе рендеринга страниц. Однако, в зависимости от вашего проекта, накладные расходы могут стать заметными. В крайних случаях это может сделать разработку нецелесообразной.

В моих наихудших сценариях я получил время отклика примерно в 50 раз медленнее при использовании панели инструментов отладки. Чтобы уменьшить накладные расходы, вы можете поиграть с настройками, описанными в документации. Я получил лучшие результаты, отключив стек-трейсинг в панелях SQL и кэша, контекст шаблона и удалив панель перенаправления:


DEBUG_TOOLBAR_CONFIG = {
    'ENABLE_STACKTRACES': False,
    'SHOW_TEMPLATE_CONTEXT': False,
    'DISABLE_PANELS': [
        'debug_toolbar.panels.redirects.RedirectsPanel',
    ]
}

В любом случае, Это должно быть полностью отключено в режиме производства с настройкой DEBUG = False.

Вернуться на верх