데이터베이스: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 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
장고 효율성 - select_relatedUno de los grandes desafíos de una aplicación cuando esta está siendo utilizada en producción, es que tenga un tiempo de...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.