반응형
✨ len()
쿼리셋은 인덱스로 접근이 가능하다. -> 길이를 재는데(쿼리셋 안 객체 수를 세는데) 파이썬의 len()함수 사용 가능.
하지만 len(queryset)을 사용하면 쿼리셋의 평가가 일어난다.

- len(queryset)은 select * from table 을 호출한다. 이 명령은 쿼리셋 내 객체의 수만큼 쿼리를 호출한다. O(n) + 이를 저장할 O(n)의 메모리가 추가로 필요하다.
✨ count()
그래서 쿼리셋을 평가하지 않고 쿼리셋 안의 객체의 숫자만 세고싶다면 항상 count()를 사용해야 한다.
queryset.count()는 SQL의 select count(*)를 호출한다.
- queryset.count()는 select count(*) from table 을 호출한다. -> 한번의 쿼리만 호출 O(1)
✨ len()을 사용하는 경우
하지만 객체들을 어차피 메모리에 올려야 한다면(사용할거라면) len()을 사용하는 것이 훨씬 빠르다.
한번 평가된 쿼리는 캐싱되기때문
len() -> 1번의 쿼리
len(queryset) # SELECT * 모든 데이터를 가져온다 - NO extra cost - 어차피 아래 for문에서 데이터를 다 불러올거임
for obj in queryset: # data is already fetched by len() - 캐시에 저장된 데이터 사용
pass
count() -> 2번의 쿼리
queryset.count() # 첫번째 db 쿼리 SELECT COUNT(*)
for obj in queryset: # 두번째 db 쿼리 (fetching data) SELECT *
pass
for문으로 쿼리셋을 순회할 것이기 때문에 어차피 모든 데이터를 불러와야한다. 그래서 이럴땐 len()을 사용하면 미리 불러진 데이터를 for문에서 사용할 수 있어서 추가쿼리가 발생하지 않게 된다.
✏️ 프로젝트 코드리뷰
category_data = {
'id' : category.id,
'name' : category.name,
'description' : category.description,
'total_products': products.count()
}
구방문방구에서 카테고리 데이터를 응답으로 줄 때 해당 카테고리 내 상품 수를 반환해줄 때 count()를 사용했는데
카테고리정보에서는 상품의 정보는 필요 없고 상품이 총 몇 개인지만 필요하기 때문에 상품 쿼리셋을 평가하지 않는 count()를 사용했다.
참고
https://stackoverflow.com/questions/14327036/count-vs-len-on-a-django-queryset
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#django.db.models.query.QuerySet.count
반응형
'Django' 카테고리의 다른 글
| Django 모델에서 기본 키 참조: pk vs id (6) | 2024.10.10 |
|---|---|
| Django | Error : you cannot alter to or from M2M fields, or add or remove through= on M2M fields (0) | 2022.08.30 |
| DRF | 페이지네이션 (0) | 2022.08.30 |
| Django | models : verbose_name (0) | 2022.08.20 |
| Django | ORM : on_delete=models.CASCADE (0) | 2022.08.14 |