최적화_한번에 모든 것을 검색하기

김동완·2022년 4월 24일
0

DB

목록 보기
15/16
post-thumbnail

INTRO

  • 위 과정까지는 중복을 제거하지 않고 단순히 쿼리 개수만 날린 것
  • 이것보다 더 큰 문제는 반복문을 도는 상황에서의 1:N, M:N 호출 상황
  • 여러번 호출 하지 말고 한 번에 모든 것을 검색해버리자 !

Retriece everythin at once if you know you will need it

  1. select_related()
    • 1:1 또는 1:N 참조 관계에서 사용
    • DB에서 INNER JOIN을 황용
  2. prefetch_related()
    • M:N 또는 1:N 역참조 관계에서 사용
    • DB가 아닌 Python을 통한 join
  • SQL의 INNER JOIN을 실행하여 테이블의 일부를 가져오고, SELECT FROM에서 관련된 필드들을 가져옴
  • 단, single-valued relationships 관계 (foreign key and one-to-one)에서만 사용 가능

'게시글의 사용자 이름까지 출력해보기'

#views.py
def index_2(request):
    articles = Article.objects.order_by('-pk')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index_2.html', context)
#templates/index_2.html
{% block content %}
  <h1>Articles</h1>
  {% for article in articles %}
    <h3>작성자 : {{ article.user.username }}</h3>
    <p>제목 : {{ article.title }}</p>
    <hr>
  {% endfor %}
{% endblock content %}

def index_2(request):
    #article을 가져올 때 user까지 결과에 추가한다. 
    articles = Article.objects.select_related('user').order_by('-pk')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index_2.html', context)

  • selected_related와 달리 SQL의 JOIN을 실행하지 않고, python에서 joining을 실행
  • select_leated가 지원하는 single-valued relationships 관계에 더해, selec_related를 사용하여 수행할 수 없는 M:N and 1:N 역참조 관계에서 사용 가능

댓글 목록을 모두 출력하기

#views.py
def index_3(request):
    articles = Article.objects.order_by('-pk')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index_3.html', context)
#templates/index_3.html
{% block content %}
  <h1>Articles</h1>
  {% for article in articles %}
    <p>제목 : {{ article.title }}</p>
    <p>댓글 목록</p>
    {% for comment in article.comment_set.all %}
      <p>{{ comment.content }}</p>
    {% endfor %}
    <hr>
  {% endfor %}
{% endblock content %}

def index_3(request):
    # articles = Article.objects.order_by('-pk')
    #article을 조회할 때 comment_set 역참조를 동시에 진행 
    articles= Article.objects.prefetch_related('comment_set')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index_3.html', context)

복합활용

댓글에 더해서 해당 댓글을 작성한 사용자 이름까지 출력 해보기

  • 1:N의 역참조와 M:참조가 동시에 진행됨
#views.py
def index_4(request):
    articles = Article.objects.order_by('-pk')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index_4.html', context)
#templates/index_4.html
{% block content %}
  <h1>Articles</h1>
  {% for article in articles %}
    <p>제목 : {{ article.title }}</p>
    <p>댓글 목록</p>
    {% for comment in article.comment_set.all %}
      <p>{{ comment.user.username }} : {{ comment.content }}</p>
    {% endfor %}
    <hr>
  {% endfor %}
{% endblock content %}

view함수 개선
def index_4(request):
    #처음에 comment_set 참조하고, user역참조 같이진행 
    articles = Article.objects.prefetch_related(Prefetch('comment_set',
    queryset=Comment.objects.select_related('user'))).order_by('-pk')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index_4.html', context)

섣부른 최적화

'작은 효율성에 대해서는, 말하자면 97%정도에 대해서는, 잊어버려라. 섣부른 최적화는 모든 악의 근원이다.'

Donald E. knuth

profile
내가 공부한 내용들이 누군가에게 도움이 될지 몰라서 쓰는 벨로그

0개의 댓글