"사전 로딩"의 두 판 사이의 차이

 
(사용자 3명의 중간 판 25개는 보이지 않습니다)
1번째 줄: 1번째 줄:
==개요==
==개요==
;eager loading
;eager loading, preloading
;eager 로딩, 이거 로딩, 사전예약 로딩, 사전 로딩, 선행 로딩, 즉시 로딩
;eager 로딩, 이거 로딩, 이른 로딩, 즉시 로딩, 사전 로딩, 선행 로딩, 조기 로딩, 프리로딩
* 로딩시 참조해야 하는 정보를 미리 명시하는 일
* 로딩시 참조해야 하는 정보를 미리 명시하는 일
* [[N+1 쿼리 문제]]의 해결을 통해 성능 향상
* 필요할 수 있는 모든 관련 데이터를 미리 한 번에 로드하는 기법
* [[ORM]] 활용시 흔히 발생할 있는 N+1 문제 해결 가능
* 이를 통해 나중에 데이터를 사용할 때 추가적인 데이터베이스 쿼리를 피할 수 있다.
* 대략 <del>저거 로딩</del>[[게으른 로딩]]의 반대개념
* 주로 ORM 프레임워크에서 사용되며, 이를 통해 성능을 향상시키고 [[N+1 문제]]를 방지할 있다.
* 대략 [[지연 로딩]]의 반대되는 개념이다.


==예시: 라라벨==
== 예시 ==
;N+1 쿼리 상황
=== 라라벨 ===
<source lang='php'>
{{소스헤더|N+1 쿼리 상황}}
<syntaxhighlight lang='php'>
foreach (Book::all() as $book)
foreach (Book::all() as $book)
{
{
     echo $book->author->name;
     echo $book->author->name;
}
}
</source>
</syntaxhighlight>
:→ <code>Book::all()</code>에는 author 정보가 없어서 Book 건수만큼 쿼리 추가 수행 (1+N회)
:→ <code>Book::all()</code>에는 author 정보가 없어서 Book 건수만큼 쿼리 추가 수행 (1+N회)
<source lang='mysql'>
<syntaxhighlight lang='mysql'>
SELECT * FROM books;
SELECT * FROM books;
SELECT * FROM authors WHERE id=1;
SELECT * FROM authors WHERE id=1;
22번째 줄: 24번째 줄:
SELECT * FROM authors WHERE id=3;
SELECT * FROM authors WHERE id=3;
... (생략)
... (생략)
</source>
</syntaxhighlight>


;eager 로딩 적용
{{소스헤더|eager 로딩 적용}}
<source lang='php'>
<syntaxhighlight lang='php'>
foreach (Book::with('author')->get() as $book)
foreach (Book::with('author')->get() as $book)
{
{
     echo $book->author->name;
     echo $book->author->name;
}
}
</source>
</syntaxhighlight>
:→ <code>Book::with('author')</code>에서 author 정보를 사용하겠다고 미리 알려줌으로써 쿼리 최소화 (2회)
:→ <code>Book::with('author')</code>에서 author 정보를 사용하겠다고 미리 알려줌으로써 쿼리 최소화 (2회)
<source lang='mysql'>
<syntaxhighlight lang='mysql'>
SELECT * FROM books;
SELECT * FROM books;
SELECT * FROM authors WHERE id IN (1, 2, 3, ...);
SELECT * FROM authors WHERE id IN (1, 2, 3, ...);
</source>
</syntaxhighlight>
 
=== Ruby On Rails ===
<syntaxhighlight lang='ruby'>
keywords = Keyword.all
keywords.each do |keyword|
  keyword.user.id
end
</syntaxhighlight>
:→ (테이블 관계 설명) <code>keywords</code> 테이블에는 <code>users</code> 테이블과 연결시킬 외래키 컬럼을 가지고 있습니다.
:→ <code>keywords</code>에는 <code>user.id</code> 정보가 없어서 <code>keyword</code> 건수만큼 쿼리 추가 수행 (1+N회)
 
<syntaxhighlight lang='mysql'>
Keyword Load (2.4ms)  SELECT "keywords".* FROM "keywords"
  User Load (4.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 9], ["LIMIT", 1]]
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 12], ["LIMIT", 1]]
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 15], ["LIMIT", 1]]
... (생략) ...
</syntaxhighlight>
 
{{소스헤더|preload(선행 로딩) 적용}}
<syntaxhighlight lang='ruby'>
keywords = Keyword.preload(:user)
keywords.each do |keyword|
  keyword.user.id
end
</syntaxhighlight>
:→ <code>Keyword.preload(:user)</code>에서  <code>users</code> 테이블의 정보를 사전에 사용하겠다고 알려줌으로써 쿼리 최소화 (2회)
<syntaxhighlight lang='mysql'>
Keyword Load (0.6ms)  SELECT "keywords".* FROM "keywords" LIMIT $1  [["LIMIT", 11]]
  User Load (1.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3, $4, $5, $6)  [["id", 9], ["id", 12], ["id", 15], ["id", 29], ["id", 28], ["id", 24]]
</syntaxhighlight>


==같이 보기==
==같이 보기==
{{z컬럼3|
* [[사전(事前)]]
* [[로딩]]
* [[ORM]]
* [[지연 로딩]]
* [[N+1 쿼리 문제]]
* [[N+1 쿼리 문제]]
* [[게으른 로딩]]
}}
* [[ORM]]
* [[eager]]
* [[로딩]]


==참고==
==참고==
48번째 줄: 83번째 줄:
*https://en.wikipedia.org/wiki/Lazy_loading
*https://en.wikipedia.org/wiki/Lazy_loading


[[분류: ORM]]
[[분류: 디자인 패턴]]
[[분류: 디자인 패턴]]

2024년 6월 19일 (수) 00:36 기준 최신판

1 개요[ | ]

eager loading, preloading
eager 로딩, 이거 로딩, 이른 로딩, 즉시 로딩, 사전 로딩, 선행 로딩, 조기 로딩, 프리로딩
  • 로딩시 참조해야 하는 정보를 미리 명시하는 일
  • 필요할 수 있는 모든 관련 데이터를 미리 한 번에 로드하는 기법
  • 이를 통해 나중에 데이터를 사용할 때 추가적인 데이터베이스 쿼리를 피할 수 있다.
  • 주로 ORM 프레임워크에서 사용되며, 이를 통해 성능을 향상시키고 N+1 문제를 방지할 수 있다.
  • 대략 지연 로딩의 반대되는 개념이다.

2 예시[ | ]

2.1 라라벨[ | ]

N+1 쿼리 상황
foreach (Book::all() as $book)
{
    echo $book->author->name;
}
Book::all()에는 author 정보가 없어서 Book 건수만큼 쿼리 추가 수행 (1+N회)
SELECT * FROM books;
SELECT * FROM authors WHERE id=1;
SELECT * FROM authors WHERE id=2;
SELECT * FROM authors WHERE id=3;
... (생략)
eager 로딩 적용
foreach (Book::with('author')->get() as $book)
{
    echo $book->author->name;
}
Book::with('author')에서 author 정보를 사용하겠다고 미리 알려줌으로써 쿼리 최소화 (2회)
SELECT * FROM books;
SELECT * FROM authors WHERE id IN (1, 2, 3, ...);

2.2 Ruby On Rails[ | ]

keywords = Keyword.all
keywords.each do |keyword|
  keyword.user.id
end
→ (테이블 관계 설명) keywords 테이블에는 users 테이블과 연결시킬 외래키 컬럼을 가지고 있습니다.
keywords에는 user.id 정보가 없어서 keyword 건수만큼 쿼리 추가 수행 (1+N회)
Keyword Load (2.4ms)  SELECT "keywords".* FROM "keywords"
  User Load (4.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 9], ["LIMIT", 1]]
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 12], ["LIMIT", 1]]
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 15], ["LIMIT", 1]]
... (생략) ...
preload(선행 로딩) 적용
keywords = Keyword.preload(:user)
keywords.each do |keyword|
  keyword.user.id
end
Keyword.preload(:user)에서 users 테이블의 정보를 사전에 사용하겠다고 알려줌으로써 쿼리 최소화 (2회)
Keyword Load (0.6ms)  SELECT "keywords".* FROM "keywords" LIMIT $1  [["LIMIT", 11]]
  User Load (1.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3, $4, $5, $6)  [["id", 9], ["id", 12], ["id", 15], ["id", 29], ["id", 28], ["id", 24]]

3 같이 보기[ | ]

4 참고[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}