Рубрики
Без рубрики

666 проектов Django проверили на неэффективные запросы к базе данных. Более половины имели эти 4 антиблокировки

Все зрелые кодовые базы содержат антиблокировки: кодовые проблемы, которые вводят дыры безопасности, технологический долг … Помечено Django, WebDev, Python, производительность.

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

Django доктор Выполняет статический анализ, чтобы найти и автоматически исправить такие проблемы. Мы проверили 666 кодовых база Django для неэффективных вызовов Django ORM и были удивлены степенью проблемы: 50% всех кодовых база Django, которые мы проверили, имели следующие антиблокировки :

  • 16% используется queryset.count ()> 0 вместо Queryset.exists ()
  • 15% используется Лен (запрос) вместо queryset.count ()
  • 10% проверено Если запрос: вместо Если QuerySet.exists ():
  • 10% не использовали иностранные ключи напрямую

Они в лучшем случае замедляют приложение Django, и в худшую сторону может принести производство.

Как бы вы решили эти результаты антиблокировки? Пытаться Наш рефакторист Performance Django .

Учитывая эти проблемы присутствовали более половины репозиториев Django GitHub, проверено, есть хороший шанс, что у вас есть хотя бы одна из этих проблем. Опытный django dev может думать, что они не сделают эти ошибки, но это не является Dev – это остров: со временем Devs Shame Teams, наследует CodeBase Brownfield, которая накапливала Tech Dovs, и будет рассмотреть код, написанный Junior Devs. Поэтому важно:

  • избегать ошибки
  • знать, как эффективно найти и исправить ошибку
  • знать, как общаться с Junior Devs Почему Это проблема.

Используя .count ()> 0 вместо .exists ()

Сравнение queryset.count () менее эффективен, чем проверять Queryset.exists () Отказ Django Docs говорит нам использовать queryset.count () Если вы хотите только подсчет, и использовать Queryset.exists () Если вы хотите узнать, существует ли хотя бы один результат.

Причина этого – потому что queryset.count () Выполняет операцию SQL, которая сканирует каждый ряд в таблице базы данных для расчета суммы. С другой стороны Queryset.exists () Просто читает одну запись в самый оптимизированный способ :

  • Удалить упорядочение
  • Удалить группировать
  • Очистить любой Dev-определенный select_related и отчетливый от запроса

Так вместо

def check_hounds():
    queryset = HoundsModel.objects.all()
    if queryset.count() > 0:
         return "oh no. Run!"

Django доктор будет автоматически исправить это:

def check_hounds():
    queryset = HoundsModel.objects.all()
    if queryset.exists():
         return "oh no. Run!"

Читать далее

Использование Len (Queryset) вместо QuerySet.count ()

Лен (запрос) Выполняет количество на уровне приложения. Это намного менее эффективно, чем делать queryset.count () , который делает расчет на уровне базы данных и просто возвращает счет.

Напроцеты – это лениво оценивается – означает, что записи не читаются из базы данных до тех пор, пока код не взаимодействует с данными. Вот почему мы можем сделать queryset.all () Не загружая каждую записи из базы данных.

Пример чего-то, что взаимодействует с данными, делает Лен (запрос) . Это Будет ли Прочитайте все записи в запросе: эффективно загрузка базы данных через Интернет. Не особенно эффективен.

С другой стороны, делая queryset.count () обрабатывает расчет на уровне базы данных, выполнив SQL, как Выберите Count (*) из таблицы Отказ Это означает использование queryset.count () делает код быстрее и улучшает производительность базы данных. Плюс представить отходы в загрузке 5000 записей только для проверки длины и выбросить их в конце!

Так вместо

def check_hounds():
    queryset = HoundsModel.objects.all()
    if len(queryset) > 2:
         return "oh no. Run!"

Django доктор будет автоматически исправить это:

def check_hounds():
    if HoundsModel.objects.count() > 2:
         return "oh no. Run!"

Сказав это, хотя, если записи будут нуждаться в чтении после проверки длины, то Лен (запрос) может быть действительным.

Читать далее

Использование в случае запроса: вместо того, чтобы если QuerySet.exists ():

Подобно выше, это может загрузить каждую строку в таблице базы данных в память, потому что запрос оценивается. Проверка, если запрос правда/falsey намного менее эффективен, чем проверка Queryset.exists () Отказ

Это особенно неэффективно, если таблица очень велика: она может привести к тому, что CPU Spike в базе данных и использует много памяти на веб-сервере. Таким образом, вместо того, чтобы вытащить каждый белый ряд со стола, проверьте Queryset.exists () , который просто пытается прочитать одну запись из таблицы очень эффективным способом.

Так вместо

def check_hounds():
    queryset = HoundsModel.objects.all()
    if queryset:
         return "oh no. Run!"

Django доктор будет автоматически исправить это:

def check_hounds():
    queryset = HoundsModel.objects.all()
    if queryset.exists():
         return "oh no. Run!"

Читать далее

Не использовать иностранные ключи напрямую

При работе с иностранными ключами доступа к model_instance.relived_field.id приведет к базе данных, когда rottle_field.id оценивается. Это можно устранить делать model_instance.related_field_id , что является внешним ключевым значением, которое Django уже кэшируется на объекте, чтобы сделать этот сценарий более эффективным.

Так вместо

def check_hounds(pk, farm_ids):
    hound = HoundsModel.objects.get(pk=pk)
    if hound.farm.id in farm_ids:
        ...

Django доктор будет автоматически исправить это:

def check_hounds(pk, farm_ids):
    hound = HoundsModel.objects.get(pk=pk)
    if hound.farm_id in farm_ids:
      ...

Читать далее

У вашего Django Code есть эти антиблокировки?

Со временем легко проскользнуть в вашей кодовой базе. Я могу проверить это для вас в django.doctor или может Просмотрите свой GitHUB PRS :

Или попробуйте Рефакторы Django Challenges Отказ

Оригинал: “https://dev.to/djangodoctor/666-django-projects-checked-for-inefficient-database-queries-over-half-had-these-4-anti-patterns-4383”