사전 학습 내용
https://yubi5050.tistory.com/60 // ORM 이란?
https://yubi5050.tistory.com/83 // ORM Queryset API
https://yubi5050.tistory.com/130 // ORM Queryset 특징
QuerySet 최적화 기법 (1) select_related & prefetch_related
일반적으로 조회(GET)시 or Serailization 과정에서 많이 발생
ORM의 Lazy Loading 특성에서 발생하는 N+1 Problem 등 의 문제를 극복하기 위해 Eager Loading (즉시 로딩) 진행
📁 select_related
- ForeignKey(1:M)의 1입장에서, OneToOne 관계 등에서 사용 가능
- SQL의 JOIN절을 사용하는 방법
📁 prefetch_related
- ForeignKey(1:M)의 M입장에서, ManyToMany 관계 등에서 사용 가능
- SQL의 WHERE … IN 구문을 사용하는 방법
- 만일 Table에서 역참조의 관계를 가질 경우 '필드명_set' 으로 참조
QuerySet 최적화 기법 (2) F() Expression
📁 F() expression
- 목적 : race conditon (경쟁 상황)을 피하기 위해 사용 & 동시성 이슈
- 상황 : 다중의 프로세스에서 같은 영역에 엑세스 하여 처리(조회, 변경 등)를 시도할 때
ex) 동시에 여러명의 유저가 특정 글에 접근하여 조회수가 업데이트 되야 하는 상황 - F expression은 파이썬 메모리 로드없이, DB 단에서 작업을 처리 → 경재 상황 해결 및 퍼포먼스 향상
QuerySet 최적화 기법 (3) Indexing 방법
- 추후 Update
QuerySet 최적화 기법 (4) 기타
📁 QuerySet.count 활용
- queryset의 길이를 호출 시 => len(queryset) 보다 count() 활용하기
- count() : DB에서 값을 계산해서 반환
- len() : lazy 메모리 로딩 -> 연산
📁 QuerySet.exists 사용
- Queryset이 1개라도 존재하는지 체크할 경우
- if Queryset 보다 exists() 활용하기
- 위 count()와 동일 이유
📁 외래키 값 직접 사용
- 외래 키 id 값만 필요한 경우
- Proejct.comment.id 말고 Project.comment_id 사용
차이점
- Project.comment.id : ForeignKey를 참조한 테이블에서 Object의 id를 가져옴)
- Project.comment_id : ForeignKey 자체에서 가져옴)
📁 values & values_list
- dict 또는 list 값을 원할 때, ORM 모델 객체가 필요하지 않은 경우 values() 를 적절하게 사용 가능
📁 QuerySet.defer & only
- 데이터베이스 불필요 열(column)이 로드되지 않도록 defer()와 only() 사용
📁 all() => filter() 로직 지양
- db 전체 호출 all() 다음 부분 호출 filter() 사용시 caching 안됨.
📁 개별 개체 정보 조회시 unique 필드나 index 열을 사용
- get()을 사용한 개별 객체를 검색시 unique 또는 db_index 열을 사용
- unique 필드나 Index로 검색시 여러 조건들에 해당되는 객체가 필터링 되지 않기 때문에 Query 속도 최적
📁 일괄 삽입, 삭제 메소드 : bulk_xxx() 사용
- 대량 삽입 (bulk_create), 대량 삭제(bulk_delete) 사용시 Query 문 갯수가 감소
📁 bulk_update() 사용시 주의점
- bulk_create는 id 값을 반환하지 않음,
- bulk로 생성된 id만 필요한 로직 구현시, 객체 목록 조회 -> bulk 생성 -> 앞에서의 객체 목록 제외한 객체 목록 조회
- 다소 비효율적인 조회가 호출됨 주의
📁 ManytoMany Field 일괄 add()
- ManytoMany Field인 Bookmark의 add 함수 이용 일괄 추가 Query 문 갯수 감소
📁 메모리 이슈 발생시 iterator() 사용
- 엑세스 해야 하는 객체가 많은 경우 QuerySet의 캐싱 동작으로 인해 많은 양의 메모리가 사용될 수 있음
- Iterator() 를 활용하여 필요한 양 로드시 성능 향상 및 메모리 감소 효과
QuerySet 최적화 기법 (6) 추가 고려 사항
📁 기타 Python이 아닌 DB에서 실행되는 로직 살펴보기
- filter() 및 exclude()를 사용하여 DB에서 필터링하는 경우
- DB에서 aggregation을 하기 위해 어노테이션하는 경우
📁 Query Debugger 기능 OFF
참고 문헌
- https://velog.io/@swhan9404/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%B5%9C%EC%A0%81%ED%99%94-ORM-%EC%B5%9C%EC%A0%81%ED%99%94-%EC%97%B0%EA%B5%AC // 프로젝트 최적화 - Django 최적화 연구
- https://leffept.tistory.com/373?category=924397 // 검색 퍼포먼스를 향상하기 전까지의 과정
- https://blog.myungseokang.dev/posts/database-access-optimization/ // Django에서 DB 액세스 최적화하기
'Python > Django' 카테고리의 다른 글
[Django] Query Profiling Tool (1) - Django debug toolbar (0) | 2022.08.12 |
---|---|
[Django] Query Profiling Tool (2) - Custom Decorator & Logger (0) | 2022.08.12 |
[Django] ORM Queryset 특징 (0) | 2022.08.08 |
[Django] django-dotenv 설정 (0) | 2022.08.08 |
[Django] 채팅 시스템 (3) UUID가 포함된 URL을 Channels Websocket이 수신하는 법 (0) | 2022.07.22 |