Django 프로그램의 최적화 기술

8423 단어 Django최적화

우정 힌트:


과도한 성능 최적화는 필요 없고 심지어 해롭다. 왜냐하면 큰 힘을 들여 가져온 밀리초급의 응답 향상은 사용자들이 전혀 느끼지 못할 수도 있다. 왜냐하면 개발자의 시간도 매우 소중하기 때문이다.

성능 최적화 지표


웹 프로젝트의 성능 최적화를 위해서는 일반적으로 여러 가지 지표를 평가해야 합니다.
  • 응답 시간
  • 최대 병렬 연결수
  • 코드의 줄수
  • 함수 호출 횟수
  • 메모리 사용량
  • CPU 비율
  • 그 중에서 응답 시간(서버가 사용자의 요청을 받고 이 요청을 처리하고 결과를 되돌려 주는 데 필요한 총 시간)은 통상적으로 가장 중요한 지표이다. 왜냐하면 너무 긴 응답 시간은 사용자를 기다리기 싫증나게 하고 다른 사이트나 앱으로 전송하기 때문이다.사용자의 수가 매우 방대해지면 최대 연결 수를 어떻게 높이고, 메모리 소모를 줄이는가도 매우 중요하다.
    개발 환경에서 우리는 일반적으로django-debug-toolbar와django-silk를 사용하여 성능 모니터링 분석을 하는 것을 권장한다.그들은 사용자가 요청할 때마다 응답 시간을 제공하고 프로그램 실행 과정(예를 들어 SQL 조회)이 가장 소모되는 시간을 알려 줍니다.
    중대형 웹 사이트나 웹 APP에 있어 웹 사이트의 성능에 가장 영향을 주는 것은 데이터베이스 조회 부분이다.첫째, 데이터베이스에서 데이터를 반복적으로 읽는 것은 시간과 계산 자원을 소모하고, 둘째, 되돌아오는 조회 데이터 집합queryset이 매우 크면 많은 메모리를 차지한다.우리는 우선 이 부분의 최적화부터 시작한다.

    데이터베이스 조회 최적화


    Queryset의 불활성과 캐시를 이용하여 중복 조회를 피하다


    Django의QuerySet의 타성과 캐시 기능을 충분히 활용하면 데이터베이스 조회 횟수를 줄일 수 있습니다.예를 들어 다음 예에서 1비례2가 좋다.왜냐하면 당신이 글 제목을 인쇄한 후에 Django는 데이터베이스 조회를 실행했을 뿐만 아니라 조회된article_list는 캐시에 넣었습니다. 다음에 다른 곳에서 다시 사용할 수 있습니다. 예2는 안 됩니다.
    
     #  1:   - Good
     article_list = Article.objects.filter(title__contains="django")
     for article in article_list:
         print(article.title)
     
     #  2: Bad
     for article in Article.objects.filter(title__contains="django"):
         print(article.title)
    그러나 때때로 우리는 조회 결과가 존재하거나 조회 결과의 수량만 알고 싶을 때,exists () 와count () 방법을 사용할 수 있습니다. 아래와 같습니다.이렇게 하면 자원을 낭비하지 않고 사용할 수 없는 데이터 집합을 조회할 수 있을 뿐만 아니라 메모리도 절약할 수 있다.
    
     #  3: Good
     article_list = Article.objects.filter(title__contains="django")
     if article_list.exists():
         print("Records found.")
     else:
         print("No records")
         
     #  4: Good
     count = Article.objects.filter(title__contains="django").count()

    한 번에 필요한 모든 관련 모델 데이터 조회


    만약에 우리가 문장 (Article) 모델을 가지고 있다면 그 유형 (Category) 은 단일 대 다의 관계 (Foreign Key) 이고, 태그 (Tag) 는 다중 대 다의 관계 (Many To Many) 이다.우리는 article_를 작성해야 한다list의 함수 보기, 목록 형식으로 문장 목록과 문장의 종류와 라벨을 표시합니다. 템플릿 파일은 다음과 같습니다.
    
     {% for article in articles %}
        <li>{{ article.title }} </li>
        <li>{{ article.category.name }}</li>
        <li>
            {% for tag in article.tags.all %}
                {{ tag.name }},
            {% endfor %}
        </li>
     {% endfor %}
    템플릿에서 매번 for 순환을 통해 관련 대상category와tag의 정보를 얻을 때마다 Django는 데이터베이스 조회를 단독으로 해야 하기 때문에 매우 큰 자원 낭비를 초래한다.우리는 select_를 충분히 사용할 수 있다관련 방법 및 prefetch_related 방법은 데이터베이스에서 단일 대 다중과 다중 다중 관련 모델 데이터를 한꺼번에 가져와서 템플릿에서 여러 번 훑어보았을 때 Django도 데이터베이스 조회를 실행하지 않습니다.
    
     #   - Bad
     def article_list(request):
         articles = Article.objects.all()
         return render(request, 'blog/article_list.html',{'articles': articles, })
     
     #   - Good
     def article_list(request):
         articles = Article.objects.all().select_related('category').prefecth_related('tags')
         return render(request, 'blog/article_list.html', {'articles': articles, })

    필요한 데이터만 조회


    기본적으로 Django는 데이터베이스에서 모든 필드를 추출하지만, 데이터 테이블에 많은 줄이 있을 때 Django에서 어떤 특정한 필드를 추출하는지 알려주는 것이 매우 의미가 있습니다.만약 우리 데이터베이스에 100만 편의 문장이 있다면, 매 문장의 제목을 순환해서 인쇄해야 한다.예를 들어 4를 조작하면 우리는 모든 글의 대상의 모든 정보를 추출하여 메모리에 불러올 것입니다. 더 많은 시간을 들여 조회할 뿐만 아니라 메모리를 대량으로 차지할 뿐만 아니라, 마지막에는 제목이라는 필드만 사용합니다. 이것은 전혀 필요하지 않습니다.우리는 values와value_를 충분히 사용할 수 있다list 방법은 필요에 따라 데이터를 추출합니다. 예를 들어 문장의 id와 title만 가져오고 조회 시간과 메모리를 절약합니다. (예6-예8)
    
     #  5: Bad
     article_list = Article.objects.all()
     if article_list:
         print(article.title)
     
     #  6: Good -  
     article_list = Article.objects.values('id', 'title')
     if article_list:
         print(article.title)
     
     #  7: Good -  
     article_list = Article.objects.values_list('id', 'title')
     if article_list:
         print(article.title)
         
     #  8: Good -  
     article_list = Article.objects.values_list('id', 'title', flat=True)
     if article_list:
         print(article.title)
    이외에도 Django 프로젝트는 defer와 only 두 가지 검색 방법을 사용하여 이 점을 실현할 수 있습니다.첫 번째는 불러오지 말아야 할 필드를 지정하고, 두 번째는 불러오지 말아야 할 필드를 지정합니다.

    페이지 나누기 사용, 최대 페이지 수 제한


    사실 앞의 코드는 더욱 최적화될 수 있다. 예를 들어 페이지를 나누어 사용자가 필요로 하는 데이터만 보여주는 것이지 모든 데이터를 한꺼번에 조회하는 것이 아니다.페이지 나누기를 사용할 때도 최대 페이지 수를 조절하는 것이 가장 좋다.예를 들어 데이터베이스에 100만 편의 글이 있을 때 한 페이지에 100편을 보여도 1만 페이지를 사용자에게 보여야 한다. 이것은 전혀 필요없다.아래와 같이 200페이지의 데이터만 보여줄 수 있습니다.
    
     LIMIT = 100 * 200
     
     data = Articles.objects.all()[:(LIMIT + 1)]
     if len(data) > LIMIT:
         raise ExceededLimit(LIMIT)
     
     return data

    데이터베이스 설정 최적화


    단일 데이터베이스를 사용하는 경우 다음과 같은 방법으로 최적화할 수 있습니다.
  • 모델을 구축할 때 CharField로 길이를 확정할 수 있는 필드는 TextField를 사용하지 않아도 저장 공간을 절약할 수 있다
  • 검색 빈도가 높은 필드 속성을 주고 모델을 정의할 때 색인(db_index=True)을 사용할 수 있습니다
  • 영구화 데이터베이스 연결..
  • 지속적인 연결이 없습니다. Django는 요청이 끝날 때까지 데이터베이스와 연결을 만듭니다.만약 데이터베이스가 로컬에 없다면, 매번 연결을 구축하고 닫는 데도 시간이 좀 걸릴 것이다.지속적인 연결 시간 설정, CONN_만 추가하면 됨MAX_AGE 매개변수는 다음과 같이 데이터베이스 설정에 적용됩니다.
    
     DATABASES = {
         ‘default': {
             ‘ENGINE': ‘django.db.backends.postgresql_psycopg2',
             ‘NAME': ‘postgres',
             ‘CONN_MAX_AGE': 60, # 60 
        }
     }
    물론 CONN_MAX_AGE도 너무 크게 설정하면 안 된다. 왜냐하면 모든 데이터베이스의 병렬 연결 수는 상한선이 있기 때문이다. (예를 들어 mysql의 기본 최대 병렬 연결 수는 100개이다.)하면, 만약, 만약...MAX_AGE 설정이 너무 크면 mysql 데이터베이스 연결 수가 급격히 상한선에 도달할 수 있습니다.동시 요청 수가 많을 경우 CONN_MAX_AGE는 30s, 10s 또는 5s와 같이 낮게 설정해야 합니다.병렬 요청 수가 높지 않을 때, 이 값은 60s나 5분 정도 길게 설정할 수 있습니다.
    사용자가 매우 많고 데이터량이 많을 때, 읽기와 쓰기 분리, 주종 복제, 분표 라이브러리의 다중 데이터베이스 서버 구조를 고려할 수 있다.이런 구조상의 구조는 모든 웹 개발 언어에 적용되는 것이지 Django에만 국한된 것이 아니라 여기서 더 이상 전개하지 않는다.

    캐시


    캐시는 데이터를 더 빨리 읽을 수 있는 매체를 통칭하며, 데이터 읽기를 가속화할 수 있는 다른 저장 방식을 가리킨다.일반적으로 임시 데이터를 저장하는데 자주 사용하는 미디어는 읽는 속도가 빠른 메모리이다.일반적으로 데이터베이스에서 필요한 데이터를 여러 번 추출하는 것은 메모리나 하드디스크 등 한 번에 읽는 것보다 비용이 많이 든다.중대형 사이트의 경우 캐시를 사용하여 데이터베이스에 대한 접근 횟수를 줄이는 것이 사이트의 성능을 향상시키는 관건 중의 하나이다.

    보기 캐시

    
     from django.views.decorators.cache import cache_page
     
     @cache_page(60 * 15)
     def my_view(request):
        ...

    @cached_ 사용property 장식기 캐시 계산 속성


    자주 변동되지 않는 계산 속성은 @cached_property 장식기 캐시 결과입니다.

    캐시 임시 데이터, 예를 들어sessions


    Django의sessions는 기본적으로 데이터베이스에 존재합니다. 그러면 모든 요청 Django는 sql로 세션 데이터를 조회하고 사용자 대상의 정보를 얻습니다.임시적인 데이터, 예를 들어sessions와messages는 캐시에 넣는 것이 가장 좋고 SQL 조회 횟수를 줄일 수 있다.
     SESSION_ENGINE = 'django.contrib.sessions.backends.cache'

    모듈 캐시


    기본적으로 Django는 요청을 처리할 때마다 템플릿 캐리어를 사용하여 파일 시스템에서 템플릿을 검색하고 이 템플릿을 렌더링합니다.너는 캐치드를 사용할 수 있다.Loader에서 템플릿 캐시 로딩을 엽니다.이 때 Django는 당신의 모델을 한 번만 찾고 해석할 수 있어 템플릿의 렌더링 효율을 크게 높일 수 있습니다.
    
     TEMPLATES = [{
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
         'DIRS': [BASE_DIR / 'templates'],
         'OPTIONS': {
             'loaders': [
                ('django.template.loaders.cached.Loader', [
                     'django.template.loaders.filesystem.Loader',
                     'django.template.loaders.app_directories.Loader',
                     'path.to.custom.Loader',
                ]),
            ],
        },
     }]
    주의: 개발 환경(Debug=True)에서 캐시 로딩을 켜는 것을 권장하지 않습니다. 템플릿을 수정한 후에 수정된 효과를 제때에 볼 수 없기 때문입니다.
    또한 템플릿 파일에서 with 탭 캐시 보기로 전송된 데이터를 다음 번에 사용할 수 있도록 권장합니다.공용 html 세션에 대해서도 캐시를 사용하는 것을 권장합니다.
    
    {% load cache %}
     {% cache 500 sidebar request.user.username %}
        .. sidebar for logged in user ..
     {% endcache %}

    정적 파일


    HTML, CSS, JavaScript 등의 정적 파일을 압축하면 대역폭과 전송 시간을 절약할 수 있습니다.Django가 자체적으로 가지고 있는 압축공은 Gzip Middleware 중간부품과 spaceless 템플릿 태그를 가지고 있다.Python을 사용하여 정적 파일을 압축하면 성능에 영향을 줄 수 있습니다. 더 좋은 방법은 아파치, Nginx 등 서버를 통해 출력 내용을 압축하는 것입니다.예를 들어 Nginx 서버는 gzip 압축을 지원하며 expires 옵션을 통해 정적 파일의 캐시 시간을 설정할 수 있습니다.
    이상은 바로 Django 프로그램의 최적화 기교에 대한 상세한 내용입니다. 더 많은 Django 프로그램의 최적화에 관한 자료는 저희 다른 관련 글을 주목해 주십시오!

    좋은 웹페이지 즐겨찾기