A 테이블에서 관계가 맺어진 B 테이블의 내용을 같이 조회하는 경우
쿼리를 통해 원래 의도한 A 테이블의 N개의 레코드를 조회한다(1회 쿼리 실행)
SELECT * FROM A;
N개 레코드 각각에 연결된 B 테이블 레코드를 조회한다(N회 쿼리 실행)
SELECT * FROM B WHERE A_id = 0;
SELECT * FROM B WHERE A_id = 1;
...
SELECT * FROM B WHERE A_id = N;
1개의 쿼리를 실행했는데 결과적으로 총 N+1개의 쿼리가 실행됨
이를 N+1 문제라고 한다
ORM을 사용할 경우 쉽게 발생한다
데이터를 실질적으로 사용할 때 로드하는 Lazy Loading 방식으로 인해 그때그때 조회 작업을 실행해서 N+1 문제가 발생한다
이러한 문제가 생기지 않게하기 위해서 A와 B 테이블을 조인한다
SELECT * FROM A LEFT OUTER JOIN B ON A.id = B.A_id
ORM마다 제공하는 조인 연산을 미리 사용해서 N+1 문제를 방지할 수 있다
Django ORM의 경우 queryset을 만들 때 select_related, prefetch_related 사용해서 해결할 수 있다
- select_related
역참조(외래키를 가지지 않은 클래스에서 외래키를 가진 클래스를 참조하는 경우 )
DB에서 INNER JOIN으로 실행 - prefetch_related
정참조(외래키를 가진 클래스에서 외래키를 가지지 않은 클래스를 참조하는 경우)
각 관계별로 DB 쿼리를 수행하고 파이썬에서 조인을 수행
Node의 TypeORM에서는 relation 옵션을 사용해서 N+1 문제를 방지할 수 있다
'기본' 카테고리의 다른 글
A* 알고리즘 (1) | 2024.03.27 |
---|---|
샤딩 (0) | 2024.03.04 |
[JavaScript] var, let, const (0) | 2024.02.27 |
객체지향 프로그래밍 (0) | 2024.02.23 |
트랜잭션 격리 수준 (0) | 2024.02.21 |
A 테이블에서 관계가 맺어진 B 테이블의 내용을 같이 조회하는 경우
쿼리를 통해 원래 의도한 A 테이블의 N개의 레코드를 조회한다(1회 쿼리 실행)
SELECT * FROM A;
N개 레코드 각각에 연결된 B 테이블 레코드를 조회한다(N회 쿼리 실행)
SELECT * FROM B WHERE A_id = 0;
SELECT * FROM B WHERE A_id = 1;
...
SELECT * FROM B WHERE A_id = N;
1개의 쿼리를 실행했는데 결과적으로 총 N+1개의 쿼리가 실행됨
이를 N+1 문제라고 한다
ORM을 사용할 경우 쉽게 발생한다
데이터를 실질적으로 사용할 때 로드하는 Lazy Loading 방식으로 인해 그때그때 조회 작업을 실행해서 N+1 문제가 발생한다
이러한 문제가 생기지 않게하기 위해서 A와 B 테이블을 조인한다
SELECT * FROM A LEFT OUTER JOIN B ON A.id = B.A_id
ORM마다 제공하는 조인 연산을 미리 사용해서 N+1 문제를 방지할 수 있다
Django ORM의 경우 queryset을 만들 때 select_related, prefetch_related 사용해서 해결할 수 있다
- select_related
역참조(외래키를 가지지 않은 클래스에서 외래키를 가진 클래스를 참조하는 경우 )
DB에서 INNER JOIN으로 실행 - prefetch_related
정참조(외래키를 가진 클래스에서 외래키를 가지지 않은 클래스를 참조하는 경우)
각 관계별로 DB 쿼리를 수행하고 파이썬에서 조인을 수행
Node의 TypeORM에서는 relation 옵션을 사용해서 N+1 문제를 방지할 수 있다
'기본' 카테고리의 다른 글
A* 알고리즘 (1) | 2024.03.27 |
---|---|
샤딩 (0) | 2024.03.04 |
[JavaScript] var, let, const (0) | 2024.02.27 |
객체지향 프로그래밍 (0) | 2024.02.23 |
트랜잭션 격리 수준 (0) | 2024.02.21 |