django의 ORM은 직관적이지만 조회할 때 날아가요.😰상스러운 말

본제에 앞서 나 개인의 의견


저는 Django의 ORM을 좋아합니다. 쉽게 실현할 수 있기 때문입니다!
왜냐하면 제가 자바를 만졌을 때(3년 전쯤) 사용한 건my batis인데 그것보다 기술량이 훨씬 적고 모델을 바탕으로 직감이 강하거든요.
하지만 딩고의 ORM은 호불호가 분명하다는 인상을 준다.
그 중에서 정적 언어 →python 등의 절차를 겪은 엔지니어들은 그다지 좋아하지 않는다.
이 가능하다, ~할 수 있다,...🤨

직관적


예를 들어 문장과 평론을 예로 들자!
class Article(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()

class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments')
    body = models.TextField()
문장과 평론의 관계는 1대 기타이다.
이런 상황은 어떻습니까?
댓글을 다 얻고 싶어요.
all_comments = Comment.objects.all()
print(all_comments)
The 느낌 쉬워!!
SQL 발매 확인 좀...
느낌은
SELECT
    project_comment.id,
    project_comment.article_id,
    project_comment.body
FROM
    project_comment;
// アプリ名がprojectだと過程します
// 実際はLIMITで件数が絞られていますが、割愛します
죠!
다음 상황은 어때요?
모든 댓글에 관련된 기사를 얻고 싶어요.
all_comments = Comment.objects.all()
for comment in all_comments:
    print(comment.article) # モデルでFK指定しているため、順参照できる
간단하여 겉과 속이 다른 직관적인 느낌을 준다!
SQL 발매 확인 좀...
SELECT project_comment.id, project_comment.article_id, project_comment.body FROM project_comment; # 4件取得できたと過程する
SELECT project_article.id, project_article.title, project_article.body FROM project_article WHERE id = [id=1のコメントのarticle_id];
SELECT project_article.id, project_article.title, project_article.body FROM project_article WHERE id = [id=2のコメントのarticle_id];
SELECT project_article.id, project_article.title, project_article.body FROM project_article WHERE id = [id=3のコメントのarticle_id];
SELECT project_article.id, project_article.title, project_article.body FROM project_article WHERE id = [id=4のコメントのarticle_id];
어!?!?
왜 이렇게 많아!?!?

귀에 낙지가 났어요.😠 N+1 질문


이것이 N+1 문제입니다.😨😨😨
슬픈 것은, 물어보는 횟수도 많지 않고, 많지도 않다는 것이다...
Join이가 만든 SQL이야...
SELECT
    project_comment.id,
    project_comment.article_id,
    project_comment.body,
    project_article.id,
    project_article.title,
    project_article.body
FROM
    project_comment
    INNER JOIN project_article
    ON project_comment.article_id = project_article.id
이렇게 될 것 같아!
전선을 잘 분해해라...
all_comments = Comment.objects.all() # クエリ1
for comment in all_comments:
    print(comment.article) # クエリ2
  • 모든 의견 조회
  • commeent에 연결된article 조회 가져오기
    (조회 2 순환 all comments)
  • values,values_list 등도 발생한다.Django REST framework면 패치에서 엄정하게 처리한 경우에도 마찬가지로 보이지 않는 곳에서 조회가 발행된다.
    나는 이것N+1問題이 모르면 나도 모르게 빠져드는 함정이라고 생각한다.

    전가의 보도🥷  select_related , prefech_related


    이것은 명확한 선포inner join,outer join이다.
    매번 검색어가 발행될 때마다 DB에 연결되기 때문에, 먼저 Join을 명확하게 설명한 다음, 한 번의 검색어로 가져옵니다.
    all_comments = Comment.objects.select_related('article').all()
    for comment in all_comments:
        print(comment.article) # クエリ飛ばない
    
    반참조의 경우는 다음과 같다.
    어떤 기사(id=5)와 관련된 모든 평론을 얻고 싶습니다.
    article = Article.objects.prefetch_related('comments').get(id=5)
    comments = article.comments.all()
    for comment in comments:
        print(comment.body)  # 先に取得しているのでクエリは発行されない
    
    참고로 사용Prefetch도 조회를 어떻게 얻는지 제어할 수 있습니다.
    article = Article.objects.prefetch_related(Prefetch(queryset=*クエリ文)).all()
    

    최후


    이렇게 Django의 ORM을 사용하려면 모델의 관계와 데이터가 어떻게 처리되는지 알아야 한다.
    데이터가 어떻게 사용되는지 깨닫고 코드를 쓰는 것은 좀 번거롭기 때문에 일반적으로 엄숙한 대상이나 데이터클래스 등으로 설계된다.
    인식된 레이어my batis와 SQL이 많이 다르지 않음😅
    모델을 직관적으로 접촉하는 것은 무엇이든 할 수 있는 것이고 위험하다.
    이 위험한 부분을 잘 이해하는 것은 Django의 ORM을 처리할 때 매우 중요하다고 생각합니다. 좋은 점도 알고 나쁜 것도 알고 정확하게 사용할 수 있는 엔지니어가 되는 것이 매우 중요합니다!
    처음 공부하는 엔지니어에게 함정이다. 이 글을 통해 가문의 보검을 머릿속 어딘가에 남기고 싶다!!!

    좋은 웹페이지 즐겨찾기