Накладные расходы на поездку туда и обратно к MySql?

StackOverflow https://stackoverflow.com/questions/1689031

  •  18-09-2019
  •  | 
  •  

Вопрос

Итак, я уже некоторое время создаю приложения на django, пью классную помощь и все такое:использовать только ORM и никогда не писать собственный SQL.

Главная страница сайта (основной интерфейс, где пользователи проводят 80–90 % своего времени) работала медленно, если у вас было большое количество пользовательского контента (например, фотографий, друзей, других данных и т. д.).

Итак, я запустил sql-логер (он был предварительно установлен в Pinax, я просто включил его в настройках) и представьте себе мое удивление, когда он сообщил об этом. 500 запросов к базе данных!!Используя написанный вручную sql, я вряд ли когда-либо запускал более 50 самых сложных страниц.

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

...даже если около дюжины запросов займут 1 мс+

Поэтому мне интересно, сколько накладных расходов требуется при обращении к mysql туда и обратно?django и mysql работают на тот же сервер поэтому не должно быть никаких накладных расходов, связанных с сетью.

Это было полезно?

Решение

Есть несколько способов уменьшить объем запросов.

  1. Использовать .filter() и .all() получить кучу вещей;выбирайте в функции просмотра (или в шаблоне через {%if%}).Python может обрабатывать пакет строк быстрее, чем MySQL.

    «Но я мог бы отправить слишком много в шаблон».Да, но вы будете выполнять меньше SQL-запросов.Измерьте, чтобы увидеть, что лучше.

    Это то, что вы делали, когда писали SQL.В этом нет ничего плохого — это не нарушает ORM, но это оптимизирует базовую работу с базой данных и помещает обработку в функцию представления и шаблон.

  2. Избегайте навигации по запросам в шаблоне.Когда вы выполняете {{foo.bar.baz.quux}}, для получения bar связан с foo, тогда baz связанный с bar, тогда quux связан с baz.Возможно, вам удастся сократить объем этих запросов, проявив некоторую осторожность. .filter() и обработка Python для сборки полезного кортежа в функции представления.

    Опять же, это то, что вы делали, когда вручную создавали SQL.В этом случае вы собираете большие пакеты объектов, управляемых ORM, в функции просмотра и выполняете фильтрацию на Python вместо множества отдельных запросов ORM.

    Это не нарушает ORM.Он меняет профиль использования с множества маленьких запросов на несколько более крупных запросов.

Другие советы

Тот факт, что вы используете ORM, не означает, что вам не следует выполнять настройку производительности.

У меня, как и у вас, была домашняя страница одного из моих приложений с низкой производительностью.Я увидел, что делаю сотни запросов, чтобы отобразить эту страницу.Я посмотрел на свой код и понял, что при осторожном использовании select_related() мои запросы приносили больше необходимых мне данных — я перешел от сотен запросов к десяткам.

Вы также можете запустить профилировщик SQL и посмотреть, нет ли индексов, которые помогли бы вашим наиболее частым запросам - ну, вы знаете, стандартным материалам базы данных.

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

Если ничего не помогает, помните:ORM великолепен, и да, вам следует попробовать его использовать, потому что это философия Django; но ты не женат на этом.

Если у вас действительно есть вариант использования, когда изучение и настройка навигации ORM не помогли, если вы уверены, что можно было бы сделать это гораздо лучше с помощью стандартного запроса:используйте в этом случае необработанный sql.

Накладные расходы на каждый запрос — это лишь часть картины.Фактическое время прохождения между вашими серверами Django и Mysql, вероятно, очень мало, поскольку большинство ваших запросов возвращаются менее чем за одну миллисекунду.Более серьезная проблема заключается в том, что количество запросов к вашей базе данных может быстро ее переполнить.500 запросов на страницу — это слишком много, даже 50 мне кажутся много.Если десять пользователей просматривают сложные страницы, у вас теперь до 5000 запросов.

Время туда и обратно до сервера базы данных является более важным фактором, когда вызывающий абонент обращается к базе данных из глобальной сети, где время туда и обратно может легко составлять от 20 до 100 мс.

Я бы определенно рассмотрел возможность использования какого-либо кэширования.

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

Когда вы делаете запрос к базе данных, она должна подготовиться к обслуживанию этого запроса, выполнив ряд действий, в том числе:

  • Выделение ресурсов (буферов памяти, временных таблиц и т. д.) для соединения/потока сервера базы данных, который будет обрабатывать запрос.
  • Десериализация SQL и параметров (это необходимо даже на одном компьютере, поскольку это межпроцессный запрос, если вы не используете встроенную базу данных)
  • Проверка существования запроса в кеше запросов, если не оптимизировать его и не поместить в кеш.
    • Также обратите внимание, что если ваши запросы не параметризованы (то есть значения не отделены от SQL), это может привести к промахам в кэше для операторов, которые должны быть одинаковыми, что означает, что каждый запрос приводит к анализу и оптимизации запроса каждый раз.
  • Обработайте запрос.
  • Подготовьте и отправьте результаты клиенту.

Это всего лишь обзор того, что делает большинство систем управления базами данных для обработки SQL-запроса.Вы несете эти накладные расходы 500 раз, даже если сам запрос выполняется относительно быстро.Итоговое взаимодействие с базой данных, даже с локальной базой данных, не так дешево, как можно было бы ожидать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top