1. 程式人生 > >(工作小總結)Django REST Framework 效能優化,簡單實現預載入功能

(工作小總結)Django REST Framework 效能優化,簡單實現預載入功能

緣由: Django 的 ORM 是惰性的每個使用者訪問網站時候,都要進行一次資料互動

在最初開發的時候,需要考慮到使用者量大的時候,
又由於 Django 的 ORM 是惰性的,它只取出當前查詢所需響應最小的資料。它不知道你是否有成百上千的相同或相似的資料也需要取出來。因此訪問網站時這勢必會對資料庫造成巨大壓力!

有句話說的是:只要你在序列化中使用巢狀關係,你就在拿你的效能開玩笑那麼怎麼解決他呢?

解決的方法是使用者訪問時候進行預載入功能,即將資料提前載入到使用者本地中。如何預載入呢?其實django已經提供了方法,在這裡我將工作中常用的載入方式貼出來:

很簡單!在你訪問量大的檢視新增:

queryset = queryset.prefetch_related('你的序列化器名')  

具體列子如下:

class CustomerSerializer(serializers.ModelSerializer):  
    orders = OrderSerializer(many=True, read_only=True)

    def setup_eager_loading(cls, queryset):
        """ Perform necessary eager loading of data. """
        queryset = queryset.prefetch_related('orders'
) return queryset

呼叫例子:

customer_qs = Customers.objects.all()  
customer_qs = CustomerSerializer.setup_eager_loading(customer_qs)  # Set up eager loading to avoid N+1 selects  
post_data = CustomerSerializer(customer_qs, many=True).data  

以上是簡單實現預載入的原理,我想各位閱讀預載入這塊,程式碼經驗應該還是有的吧??那我就直接貼出比較具體的程式碼塊了,實現預載入功能!

  1. 首先建立一個簡單的資料模型類:
from django.contrib.auth.models import User

class Event:  
    """ A single occasion that has many `attendees` from a number of organizations."""
    creator = models.ForeignKey(User)
    name = models.TextField()
    event_date = models.DateTimeField()

class Attendee:  
    """ A party-goer who (usually) represents an `organization`, who may attend many `events`."""
    events = models.ManyToManyField(Event, related_name='attendees')
    organization = models.ForeignKey(Organization, null=True)

class Organization:  
    name = models.TextField()

2.預載入程式碼如下:

class EventSerializer(serializers.ModelSerializer):  
    creator = serializers.StringRelatedField()
    attendees = AttendeeSerializer(many=True)
    unaffiliated_attendees = AttendeeSerializer(many=True)

    @staticmethod
    def setup_eager_loading(queryset):
        """ Perform necessary eager loading of data. """
        # select_related for "to-one" relationships
        queryset = queryset.select_related('creator')

        # prefetch_related for "to-many" relationships
        queryset = queryset.prefetch_related(
            'attendees',
            'attendees__organization')

        # Prefetch for subsets of relationships
        queryset = queryset.prefetch_related(
            Prefetch('unaffiliated_attendees', 
                queryset=Attendee.objects.filter(organization__isnull=True))
            )
        return queryset

總結:以上是django中實現預載入功能,總之:任何時候你通過 ORM 查詢巢狀關係時,你都應該考慮建立適合的預載入。