Я новичок в Django и базах данных, поэтому я пытаюсь получить представление о производительности. В частности, я хочу понять, работает ли select_related()
так, как я думаю.Django: Использование Select_related() и время выполнения исполнения
Вот упрощенная версия моей модели:
class User(models.Model):
short = models.CharField(max_length=255)
name = models.CharField(max_length=255)
class Comment(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
short = models.ForeignKey(User)
В моем шаблоне, я должен показать короткое имя пользователя рядом с заголовком комментария. Размер тестовой базы данных составляет 1000 пользователей и 19000 комментариев.
Во-первых, я был получение списка следующим образом:
cmt_list = Comment.objects.all().order_by('title')
Мой шаблон был доступ к внешнему ключу short
, который вызывает дополнительные обращения к базе данных. Получение всех полученных данных ~ 30s. Это было ужасно.
Я знал, что это намного быстрее - это сырой SQL, и я не мог понять, как это сделать с помощью Django ORM. Таким образом, я использовал интерфейс низкого уровня:
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT app_comment.title,app_user.short \
FROM app_comment,app_user \
WHERE app_comment.short_id=app_user.id \
ORDER BY app_comment.title"
)
raw_list = cursor.fetchall()
cmt_list = [ {"title":entry[0], "short":entry[1]} for entry in raw_list]
ВОССТАНОВЛЕНИЕ все данные взяли ~ 233ms. Это то, чего я ожидал!
После прочтения большего количества документов я обнаружил функцию select_related()
в Django. Итак, я попробовал, что:
cmt_list = Comment.objects.all().select_related('short__short').order_by('title')
Получение всех данных взял ~ 1.3s. Гораздо лучше, чем оригинал, но все же довольно медленный по сравнению с необработанными SQL-запросами.
Вопрос
Что я делаю не так в том, что я использую select_related (отдельно)/Django ORM? Я понимаю, что ORM добавит некоторые накладные расходы, но 1.3s против 233ms кажется чрезмерным. Или это ожидалось, и мне просто нужно преодолеть это?
Как я могу создать запрос с использованием ORM, который был бы эквивалентен необработанному SQL-запросу, который я сделал? Учитывая то, что я понимаю о select_related(), мой исходный SQL-запрос и мой Django должны быть примерно эквивалентными. (Запрос Django будет захватывать больше контента, но для моих тестовых данных их было бы не намного больше.)
Вы можете посмотреть сгенерированный запрос, напечатав 'Comment.objects.select_related ('short'). Order_by ('title'). Query'. –
Если вы хотите проверить, вызвана ли разница из-за дополнительных служебных данных (например, что Django извлекает «контент»), загляните в '.only()' или '.defer()'. –
Ах, ха! Я не понимал, насколько легко было увидеть запрос, который делал Django. Это упростит мои тесты. Спасибо @KevinChristopherHenry. – hoadlck