Являются ли запросы с использованием related_name более производительными в Django? - PullRequest
1 голос
/ 22 июня 2019

Допустим, у меня настроены следующие модели:

class Shop(models.Model):
    ...

class Product(models.Model):
    shop = models.ForeignKey(Shop, related_name='products')

Теперь предположим, что мы хотим запросить все товары из магазина с помощью label 'demo', цена которого ниже $ 100.Есть два способа сделать это:

shop = Shop.objects.get(label='demo')
products = shop.products.filter(price__lte=100)

Или

shop = Shop.objects.get(label='demo')
products = Products.objects.filter(shop=shop, price__lte=100)

Есть ли разница между этими двумя запросами?Первый использует свойство related_name.Я знаю, что внешние ключи индексируются, поэтому поиск по ним должен быть быстрее, но применимо ли это в нашей первой ситуации?

1 Ответ

2 голосов
/ 22 июня 2019

Краткий ответ : это приведет к эквиваленту запросов.

Мы можем сделать тест, напечатав запросы:

>>> print(shop.products.filter(price__lte=100).query)
SELECT "app_product"."id", "app_product"."shop_id", "app_product"."price" FROM "app_product" WHERE ("app_product"."shop_id" = 1 AND "app_product"."price" <= 100)
>>> print(Product.objects.filter(shop=shop, price__lte=100).query)
SELECT "app_product"."id", "app_product"."shop_id", "app_product"."price" FROM "app_product" WHERE ("app_product"."price" <= 100 AND "app_product"."shop_id" = 1)

за исключением того, что условия в WHERE поменялись местами, оба равны. Но обычно это не имеет никакого значения на стороне базы данных.

Если вы, однако, не заинтересованы в самом объекте Shop, вы можете выполнить фильтрацию с помощью:

products = Product.objects.filter(<b>shop__label='demo'</b>, price__lte=100)

Это сделает JOIN на уровне базы данных и, таким образом, извлечет данные за один проход:

SELECT "app_product"."id", "app_product"."shop_id", "app_product"."price"
FROM "app_product"
INNER JOIN "app_shop" ON "app_product"."shop_id" = "app_shop"."id"
WHERE "app_product"."price" <= 100 AND "app_shop"."label" = demo
...