Приветствую!
В Django я новичок (реальной практики не было, только пара простеньких курсов), сейчас по работе решаю задачу - интерфейс для довольно крупной БД.
На данный момент столкнулся с затыком вытягивания данных по фильтру с несколькими условиями, одно из них - отсеивание значений, не равных "-" (по сути, пустое). Сколько уже бьюсь - везде нахожу, что надо использовать exclude, но в этом случае запрос начинает выполняться не пару секунд, а несколько минут (до конца ни разу так и не дождался), проанализировал генерируемый query - зачем-то вместо простого != он генерит вложенный запрос, который ищет указанное значение во всей (!) таблице (3,5 млн записей на данный момент) без учета других условий, а затем уже из найденного фильтрует то, что совпадает с нормальными фильтрами.
Как пример набросал такую модель:
class Model1(models.Model):
name = models.TextField()
class Model2(models.Model):
model1 = models.ForeignKey(Model1, on_delete=models.CASCADE)
name = models.TextField()
class Model3(models.Model):
name = models.TextField()
model2 = models.ForeignKey(Model2, on_delete=models.CASCADE)
Выполняю запрос, аналогичный рабочему (для наглядности фильтр только по одному полю):
print(Model1.objects.filter(model2__name='m2').exclude(model2__model3__name='m3').query)
Вывод:
'SELECT "db_model1"."id", "db_model1"."name" FROM "db_model1" INNER JOIN "db_model2" ON ("db_model1"."id" = "db_model2"."model1_id") WHERE ("db_model2"."name" = m2 AND NOT ("db_model1"."id" IN (SELECT U1."model1_id" FROM "db_model2" U1 INNER JOIN "db_model3" U2 ON (U1."id" = U2."model2_id") WHERE U2."name" = m3)))'
Хотя вроде как логика подсказывает использовать просто:
'SELECT "db_model1"."id", "db_model1"."name" FROM "db_model1" INNER JOIN "db_model2" ON ("db_model1"."id" = "db_model2"."model1_id") INNER JOIN "db_model3" ON ("db_model2"."id" = "db_model3"."model2_id") WHERE "db_model2"."name" = m2 AND "db_model3"."name" != m3'
Такой запрос по времени работает практически как голый SQL. Можно ли как-то реализовать нормальное формирование запроса через ORM или все же для таких объемов данных лучше использовать чистый SQL везде, где можно?
Заранее благодарю.