Django ORM: Почему exclude() работает так медленно и как его оптимизировать?
В моем CBV есть следующие 3 запроса:
filtered_content = Article.objects.filter_articles(search_term)
filtered_articles = filtered_content.exclude(source__website=TWITTER)
filtered_tweets = filtered_content.filter(source__website=TWITTER)
Краткое объяснение: Я запрашиваю свою базу данных (PostgreSQL) для всех названий статей, которые содержат поисковый термин. После этого я разделяю результаты на одну переменную, которая содержит все статьи, происходящие из Twitter, а другая переменная содержит все статьи, происходящие со всех других сайтов.
У меня есть два вопроса по поводу оптимизации этих запросов.
Вопрос 1: Если посмотреть на среднее время выполнения этих запросов, то оно не имеет смысла (filtered_content = менее 0,001 секунды, filtered_articles = 0,2 секунды и filtered_tweets = 0,04 секунды). В чем причина того, что оператор exclude() (filtered_articles) работает так медленно? Я также попробовал выполнить запрос другим способом, но это оказалось еще медленнее:
filtered_content = Article.objects.filter_articles(search_term)
filtered_tweets = filtered_content.filter(source__website=TWITTER)
filtered_content.exclude(article_id__in=[tweet.article_id for tweet in filtered_tweets])
Вопрос 2: Есть ли более элегантный способ решить эту проблему / есть ли способ сделать это менее чем за 3 отдельных запроса? Более конкретно, используя Django ORM, есть ли способ сделать запрос, в котором все исключенные() объекты хранятся в одной переменной, а все неисключенные объекты хранятся в другой?
Я не знаю, почему это медленнее, возможно, вам нужно проверить sql, который генерирует exclude. С другой стороны, вы можете попробовать использовать Q statment:
from django.db.models import Q
Article.objects.filter(~Q(source__website=TWITTER)).filter_articles(search_term)
Можете поделиться своим методом .filter_articles()?