Есть ли недостаток в добавлении нескольких индексов к модели в Django?
Я работаю над django dashboard для отображения данных в серии графиков, и поэтому мне нужно установить различные dataframes из моих моделей.
Когда я загружаю приборную панель в продакшене, на отрисовку представления уходит около 15 секунд. Другой приборной панели требуется 40. После анализа моего кода выяснилось, что мои запросы занимают очень много времени. Я думал, что это не так, поскольку моя модель Order содержит около 600k объектов, а фильтры order_date должны сократить их до 30k максимум.
Ниже представлена моя модель:
class Order(models.Model):
order = models.IntegerField(db_index=True, default=0)
region = models.CharField(max_length=3, default="")
country = models.CharField(db_index=True, max_length=2, default="")
order_date = models.DateTimeField(db_index=True, default=datetime.datetime.now)
user_name = models.CharField(db_index=True, max_length=256, null=True)
order_status = models.CharField(max_length=256, null=True)
quote_status = models.CharField(max_length=256, null=True)
purchase_status = models.CharField(max_length=256, null=True)
q_to_r = models.FloatField(db_index=True, null=True)
r_to_p = models.FloatField(db_index=True, null=True)
А вот фрагмент кода, на оценку которого уходит 15 секунд:
month = [4, 2022]
country = ["US", "CA", "UK"]
user_list = ["Eric", "Jane", "Mark"]
all_objects = Order.objects
first_data = all_objects.filter(order_date__month=month[0], order_date__year=month[1],
country__in=country, order_status__in=order_status,
quote_status__in=quote_status,
purchase_status__in=purchase_status, user_name__in=user_list)
order_data = first_data.values_list("order", flat=True)
country_data = first_data.values_list("country", flat=True)
df = pd.DataFrame({"Order": order_data,
"Country": country_data})
В частности, экземпляр df занимает большую часть времени рендеринга представления.
Любой вклад будет оценен по достоинству. Я пытался добавить индексы в мою модель, безрезультатно.
Заранее спасибо!
Фильтры в Django преобразуются в операторы WHERE с AND. Обычно можно ускорить выполнение таких запросов, поставив индекс на каждое поле, которое используется в операторе фильтрации, например,
.order_date,country,order_status,quote_status,purchase_status,user_name. Однако имейте в виду, что индекс, используемый СУБД, может варьироваться, и вам следует запустить профилировщик запросов, например, SQL EXPLAIN, чтобы понять, какие индексы дают ожидаемый эффект.Я ожидал, что такие поля, как страна и пользователь, будут внешними ключами, а не простыми списками. Если у вас есть FK, вам нужно добавить
.select_related()в запрос, чтобы убедиться, что вы выполняете SQL-соединение, а не загружаете их по одному.Для достижения наилучших результатов я рекомендую использовать профилировщик, например django-debug-toolbar, который может сильно помочь в определении узких мест в ваших запросах и поиске правильного подхода.