Эффективные запросы в django Query
Мы работаем над созданием газеты с помощью django. Прежде чем читать дальше, позвольте мне показать вам код.
# Fetch lead, top, and other filtered news
news_objects = news.objects.filter(website=host, is_published__in=[True], published_date__lt=current_datetime).only('Category','title','news_brief','image','img_caption','published_date','news_id')
lead = news_objects.filter(status='lead').order_by('-published_date').first()
top = news_objects.filter(status='top').order_by('-published_date')[:4]
filtered_news = news_objects.exclude(status__in=['lead', 'top']).order_by('-published_date')
# Fetch filtered categories and prefetch limited news related to filtered categories
categories_with_news = catagory.objects.filter(website=host, show_front__in=[True]).prefetch_related(
Prefetch('catagory', queryset=filtered_news, to_attr='limited_news')
)
# Limit the news to the first 5 for each category
for category in categories_with_news:
category.limited_news = category.limited_news[:6]`
Нижеприведенный код будет собирать все новости в определенном домене. Новости содержат более 10k
news_objects = news.objects.filter(website=host, is_published__in=[True], published_date__lt=current_datetime).only('Category','title','news_brief','image','img_caption','published_date','news_id')
Нижеприведенный код получит только 5 новостей из news_objects
lead = news_objects.filter(status='lead').order_by('-published_date').first()
top = news_objects.filter(status='top').order_by('-published_date')[:4]
Ниже приведен код, который получит все категории, которые будут отображаться впереди вместе с их данными.
categories_with_news = catagory.objects.filter(website=host, show_front__in=[True]).prefetch_related(
Prefetch('catagory', queryset=filtered_news, to_attr='limited_news')
)
Помимо этого, приведенный ниже код будет получать 6 новостей для каждой категории.
for category in categories_with_news:
category.limited_news = category.limited_news[:6]
Здесь моя проблема в том, что я не думаю, что это хорошая идея, чтобы получить все новости, потому что мне нужно не более 60 новостей. Как сделать это эффективно.
Я попробовал ограничить запрос до 300, но и тут возникла проблема, возможно, в какой-то категории №6 может находиться на 350 позиции.
Несколько вещей:
- не итерируйте
categies_with_news
, устанавливайте ограничения, когда это действительно необходимо (например, время сериализации/ответа). - не используйте
__in=[True]
, вместо этого используйте=True
. - убедитесь, что вы индексируете
status
published_date
website
- Убедитесь, что ваши ответы постранично оформлены.
#1 - ваш главный убийца.
для такого запроса с <10 миллионами записей время ответа должно составлять около .2 +-.1 с или около того.
Как часто появляются новые новости? Я предполагаю, что извлечение новостей - гораздо более частая операция, чем добавление новых новостей. Поэтому добавьте немного больше работы к менее частой операции. В общем, храните в БД некоторую дополнительную информацию, которая меняется довольно редко, чтобы ускорить запросы на поиск.
Вы можете поддерживать флаг top_six для своих новостных объектов. Каждый раз, когда добавляется новая новость, получайте текущую шестерку лучших в категории new_new, снимайте флаг для той, которая больше не входит в шестерку из-за нового добавления, и добавляйте новую с установленным флагом. Вероятно, вам также нужно выполнять ежечасную? ежедневную? операцию, чтобы взять все top_six и снять флаг с тех, которые слишком устарели (или, может быть, непопулярны?), чтобы сохранить статус.
Получение текущей шестерки лучших для некоторых или всех категорий будет фильтроваться по этому флагу. В этом случае вам не придется перебирать категории с новостями или срезами для их извлечения. Вы никогда не получите более шести новостей в любой категории, но один запрос к БД может получить новости по всем или нескольким (__in
) категориям.