其他分享
首页 > 其他分享> > select_related和prefetch_related的使用

select_related和prefetch_related的使用

作者:互联网

首选明确一点,这两个都是发生在表连接中,为了避免不必要的数据查询而存在

创建模型类

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=300)

    def __str__(self):
        return self.name

class Book(models.Model):
    name = models.CharField(max_length=300)
    price = models.IntegerField(default=0)
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

    class Meta:
        default_related_name = 'books'

    def __str__(self):
        return self.name

class Store(models.Model):
    name = models.CharField(max_length=300)
    books = models.ManyToManyField(Book)

    class Meta:
        default_related_name = 'stores'

    def __str__(self):
        return self.name

select_related

使用前:查到book的queryset,然后又到数据库中通过publisher.id查询publish.name,两次进入数据库,效率低

	queryset = Book.objects.all()
    
    books = []
    for book in queryset:
        books.append({'id': book.id, 'name': book.name, 'publisher': book.publisher.name})
        
    return books
 

使用后:在第一次查询时通过SQL语句中使用join将数据预读取,就不用在此查询数据库,效率高

	queryset = Book.objects.select_related('publisher').all()

    books = []

    for book in queryset:
        books.append({'id': book.id, 'name': book.name, 'publisher': book.publisher.name})

    return books
 

 

只能查询多对一或者一对一,也就是对象的外键属性是一个对象如果是一个集合,就需要用到prefetch_related

prefetch_related

使用前:第一次查询得到queryset,然后又对其中每个对象的"外键"属性进行all查询效率低

    queryset = Store.objects.all()

    stores = []

    for store in queryset:
        books = [book.name for book in store.books.all()]
        stores.append({'id': store.id, 'name': store.name, 'books': books})

    return stores
 

 

使用后:分别查询每一个表,然后在python语言层面上进行连接,效率比前者高

    queryset = Store.objects.prefetch_related('books')

    stores = []

    for store in queryset:
        books = [book.name for book in store.books.all()]
        stores.append({'id': store.id, 'name': store.name, 'books': books})

    return stores
 

prefetch_related 灵活的使用

    queryset = Store.objects.prefetch_related('books')

    stores = []
    for store in queryset:
        books = [book.name for book in store.books.filter(price__range=(250, 300))]
        stores.append({'id': store.id, 'name': store.name, 'books': books})

    return stores
   
  1. 显示对Store表进行查询,然后对Book查询,得到数据,连接;
  2. 再循环中使用的filter方法过滤了一部分数据,使得连接的数据无法使用
  3. 与最笨的方法比,不仅多查了Book表,还进行了连接,最后连接的数据没有用到,浪费。
    queryset = Store.objects.prefetch_related(
       Prefetch('books', queryset=Book.objects.filter(price__range=(250, 300))))

   stores = []
   for store in queryset:
       books = [book.name for book in store.books.all()]
       stores.append({'id': store.id, 'name': store.name, 'books': books})

   return stores
 

queryset = Store.objects.prefetch_related( Prefetch('books', queryset=Book.objects.filter(price__range=(250, 300))))

标签:store,name,queryset,related,books,prefetch,book,select
来源: https://www.cnblogs.com/kylin5201314/p/14738195.html