2017-11-07 6 views
0

내 django 앱은 django-rest-framework 및 MySQL을 사용합니다. 앱을 테스트했지만 기능이 거의 없습니다. 응답 시간이 길었습니다. 나는 그 문제가 뭔지 모른다.python django 응답 시간이 길지만 무엇이 잘못되었는지 알 수 없음

이것은 가장 긴 응답 시간 기능 중 하나입니다.

180232 function calls (171585 primitive calls) in 1.110 seconds 

    Ordered by: internal time 
    List reduced from 757 to 151 due to restriction <0.2> 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     105 0.597 0.006 0.597 0.006 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:268(query) 
     2 0.154 0.077 0.174 0.087 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:81(__init__) 
     4 0.020 0.005 0.020 0.005 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:254(autocommit) 
8800/3582 0.010 0.000 0.828 0.000 {built-in method builtins.getattr} 
    20156 0.010 0.000 0.022 0.000 {built-in method builtins.isinstance} 
    200/100 0.009 0.000 0.886 0.009 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/rest_framework/serializers.py:479(to_representation) 
     2 0.009 0.005 0.009 0.005 {function Connection.set_character_set at 0x109b506a8} 
    6920 0.009 0.000 0.009 0.000 {built-in method builtins.hasattr} 
             .... 

이 기능은 목록의 첫 번째 페이지이며 총 개수는 1000이고 페이지 크기는 100입니다. 각 레코드는 하나의 테이블에 합류합니다. 쿼리가 오랜 시간이 걸렸으므로 Django ORM을 원시 쿼리로 변경했지만 시간은 같습니다. 나는 그것이 60ms 미만을 생각합니다

 2199 function calls (2133 primitive calls) in 0.195 seconds 

    Ordered by: internal time 
    List reduced from 419 to 84 due to restriction <0.2> 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     2 0.153 0.076 0.169 0.084 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:81(__init__) 
     4 0.016 0.004 0.016 0.004 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:254(autocommit) 
     3 0.014 0.005 0.014 0.005 /Users/jyj/.pyenv/versions/logispot_app_env/lib/python3.6/site-packages/MySQLdb/connections.py:268(query) 
     2 0.008 0.004 0.008 0.004 {function Connection.set_character_set at 0x109b506a8} 

에도 인증 확인 응답 시간 (어쩌면 내가 잘못 원시 쿼리를 사용). (어쩌면 내 생각이 잘못되었습니다)

django 쿼리가 너무 느리거나 내 응용 프로그램에 문제가 있습니까? 나는 그 문제가 무엇인지 압니다.

  • DEBUG은 단지 지역 runserver 배포하지 False
  • settings입니다. 하지만 배포 할 때 응답 시간은 거의 동일합니다 (더 빠르게 배포되지만 질의 시간은 동일).
  • 정보가 좋지 않아 죄송합니다. 내 웹 개발 경험은 반년 밖에되지 않습니다. 당신이 더 원하면, 나는 시도 할 것이다.

편집 보기 코드

class OrderListCreationAPI(generics.ListCreateAPIView): 
    permission_classes = (
     permissions.IsAuthenticatedOrReadOnly, 
     IsAdminOrClient, 
    ) 
    pagination_class = StandardListPagination 


    def get_queryset(self): 
     if self.request.method == 'GET': 
      queryset = CacheOrderList.objects.all() 
      return queryset 
     else: 
      return Order.objects.all() 

    def get_serializer_class(self): 
     if self.request.method == 'GET': 
      return CacheOrderListSerializer 
     else: 
      return OrderSerializer 

시리얼 코드

class CacheOrderListSerializer(serializers.ModelSerializer): 
    base = CacheBaseSerializer(read_only=True) 

    class Meta: 
     model = CacheOrderList 
     fields = '__all__' 

모델 코드

class CacheBase(models.Model): 
    created_time = models.DateTimeField(auto_now_add=True) 
    order = models.OneToOneField('order.Order', on_delete=models.CASCADE, related_name='cache', primary_key=True) 
    driver_user = models.ForeignKey('member.DriverUser', on_delete=models.SET_NULL, null=True) 
    client_name = models.CharField(max_length=20, null=True) 
    load_address = models.CharField(max_length=45, null=True) 
    load_company = models.CharField(max_length=20, null=True) 
    load_date = models.DateField(null=True) 
    load_time = models.CharField(max_length=30) 
    unload_address = models.CharField(max_length=45, null=True) 
    unload_company = models.CharField(max_length=20, null=True) 
    unload_date = models.DateField(null=True) 
    unload_time = models.CharField(max_length=30) 
    stop_count = models.IntegerField(default=0) 
    is_round = models.BooleanField(default=False) 
    is_mix = models.BooleanField(default=False) 
    car_ton = models.CharField(max_length=15, null=True) 
    weight = models.FloatField(null=True) 
    payment_method = models.BooleanField(default=s.ORDER_PAYMENT_METHOD_ADVANCE) 
    contract_fee = models.IntegerField(null=True) 
    driver_fee = models.IntegerField(null=True) 
    order_fee = models.IntegerField(null=True) 
    is_deleted = models.BooleanField(default=False) 


class CacheOrderList(models.Model): 
    base = models.OneToOneField(CacheBase, on_delete=models.CASCADE, related_name='order_list') 
    order_status = models.IntegerField(null=True) 
    order_created_time = models.DateTimeField(null=True) 
    car_type = models.CharField(max_length=10, null=True) 
    asignee = models.CharField(max_length=20, null=True) 
    objects = CacheManager() 

    class Meta: 
     ordering = ('-order_created_time',) 
     db_table = 'CacheOrderList' 

EDIT2 enter image description here 목록 기능에서 앱은 이미 100 개 항목을 가져 오지만 그 이후에는 1 개당 1 개씩 다시 조회합니다. 아직 가져온 항목은 사용하지 않습니다. 따라서 각 쿼리에 소요되는 시간은 100 * 시간이 걸립니다.

이것은 아마도 serializer가 페이지 매김이 가진 레코드를 사용하지 않았기 때문일 수 있습니다. 그래서 페이지 매김 2 쿼리 + 시리얼 라이저 100 쿼리 + 다른.

나는 그 일이 왜 일어 났는지 알지 못합니다.

+0

당신이 얼마나 많은 행이? mysql에서 같은 쿼리를 직접 실행 해 보았습니까? –

+0

약 1000입니다. 그리고 나는 mysql에서 실행합니다. 그것은 60ms보다 적게 걸렸다. 내 응용 프로그램에서 원시 쿼리 (동일한 쿼리)를 사용하도록 코드를 변경했습니다. 시간은 내 게시물 결과와 동일합니다. –

+0

코드를 게시 할 수 있습니까? –

답변

1

기본 필드에 대한 CacheOrderList 쿼리 세트에서 select_related을 사용하십시오. 이것은 메소드에서 제공하는 외래 키 연관을 가진 쿼리 세트 캐시를 준비합니다. 기본적으로 DB에 반복해서 도달하지는 않습니다.

:

def get_queryset(self): 
    if self.request.method == 'GET': 
     # prepare related models cache using `select_related` 
     queryset = CacheOrderList.objects.all().select_related('base') 
     return queryset 
    else: 
     return Order.objects.all() 
+0

고맙습니다. 나는이 지위를 보았다. http://ses4j.github.io/2015/11/23/optimizing-slow-django-rest-framework-performance/ –