데이터베이스:django ORM에서 N+1 쿼리를 처리하는 방법
기본 장면
class Category(models.Model):
name = models.CharField(max_length=30)
class Article(models.Model):
title = models.CharField(max_length=30)
body = models.TextField()
category = models.ForeignKey(Category)
time = models.DateTimeField()
#----
{% for a in Article.objects.all %}
{{ a.title }}
{{ a.category.name }}
{% endfor %}
목록 페이지를 생성할 때 먼저 한 번 실행합니다
select * from article limited 0,N
그리고 캐티gory를 하나씩 가져오세요.name, N번 더 실행
select name from category where id = category_id
그래서 N+1문제는 사실 1+N문제라고 해야 하는데 이것은 데이터베이스 디자인 모델의 문제일 뿐이다.그러나 데이터베이스에 큰 압력을 가져올 수 있다. 간단한 목록 페이지에 수백 번의 데이터베이스 조회가 있을 수 있다
N+1문제는 ORM만의 문제가 아니라 orm을 사용할 때 데이터베이스 테이블의 줄이 하나의 대상이 되기 때문에 자연스레 위의 방법으로 조회하기 쉽고 orm을 사용하지 않고 프로그래밍을 하는 경우 하위 조회나 inner join을 직접 사용한다.
select a.*,c.name from article a,category b where a.category_id = b.id
하위 조회나 inner join은 데이터베이스에 있어서도 자원을 많이 쓰는 작업이다. 왜냐하면 시계를 잠가야 하기 때문에 높은 병발 상태에서는 쉽게 잠겨 죽기 쉽다.
1+N 문제를 해결하려면 보통 3가지 방법이 있어요.
그래서 이런 방안은 분명히 저장 효율이 높지 않지만 이 두 가지 상황을 최적화하면 좋은 해결 방법이라고 할 수 있다. MongoDB는 이렇게 한 것이다
select *,category_id from article limited 0,N
를 실행한 다음 결과 목록을 훑어보고 모든categoryid, 중복 항목을 제거하고 다시 실행select name from category where id in (category id list)
하위 조회/join 조회를 두 번으로 나누는 것은 높은 병발 사이트 데이터베이스 조정에서 매우 효과적인 흔한 방법이다. 비록 더 많은 cpu 시간을 들일 수 있지만 시스템의 잠금을 피하고 병발 응답 능력을 향상시켰다.
데이터베이스 자체는 높은 합병을 처리할 수 없다. 왜냐하면 우리는 단일 데이터 항목의 조작이 원자라는 것을 보장할 수 있을 뿐이고 데이터베이스의 조회는 목록을 기본 단원으로 하기 때문에 이것은 천연적인 모순이고 해석이 없다.
데이터베이스 디자인 모델은 웹 프레임워크 능력 범위 내에 있지 않기 때문에django의 ORM은 뒤의 두 가지 방법만 지원한다
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Laravel의 전역 범위, 쉬운 방법.예를 들어 특정 역할에 대한 쿼리를 반복하는 자신을 발견한 적이 있습니다. 실제로 전역 범위가 필요한 시나리오를 가정해 보겠습니다. 주문 테이블이 있고 무료 주문과 유료 주문이 있습니다. 클라이언트는 자신의 주문만 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.