196 lines
5.2 KiB
JSON
196 lines
5.2 KiB
JSON
{
|
|
"version": "1.1",
|
|
"title": "배치는 부모를 먼저 페이징하고 자식을 IN으로 따로 가져온다",
|
|
"question": "배치 페치는 어떤 순서로 부모 페이징과 자식 조회를 나누는가?",
|
|
"type": "sequence",
|
|
"direction": "TB",
|
|
"audience": [
|
|
"컬렉션 N+1과 페이징을 함께 다루는 백엔드 개발자"
|
|
],
|
|
"summary": "부모만 LIMIT으로 페이징한 뒤 초기화되지 않은 프록시를 모아 자식을 IN으로 조회한다.",
|
|
"alt": "조회 코드, Hibernate 세션, feed_items, highlights 네 참여자 사이에서 부모 페이징이 먼저 일어나고 그다음 자식 IN 배치 조회가 일어나는 순서도.",
|
|
"long_description": "조회 코드가 부모 페이지를 요청하면 세션이 feed_items에 부모만 LIMIT으로 조회한다. 돌아온 부모에는 초기화되지 않은 컬렉션 프록시가 붙어 있다. 세션은 그 프록시를 batch fetch size만큼 모아 highlights를 WHERE fk IN 으로 조회하고, 받은 자식 행으로 컬렉션을 채워 조회 코드에 돌려준다.",
|
|
"composition": {
|
|
"profile": "sequence",
|
|
"diagram_only": true,
|
|
"reference_ids": [
|
|
"payment-approval-sequence"
|
|
],
|
|
"rationale": "부모 페이징이 자식 조회보다 먼저 일어난다는 순서 자체가 배치가 페이징을 지키는 이유이므로, 정적 구성도가 아니라 시간 순서로 그린다."
|
|
},
|
|
"groups": [],
|
|
"nodes": [
|
|
{
|
|
"id": "loader",
|
|
"label": "조회 코드",
|
|
"kind": "actor",
|
|
"role": "participant",
|
|
"shape": "actor",
|
|
"description": "페이지를 요청하는 애플리케이션 코드",
|
|
"evidence": [
|
|
{
|
|
"start_line": 1009,
|
|
"end_line": 1010
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "session",
|
|
"label": "Hibernate 세션",
|
|
"kind": "service",
|
|
"role": "participant",
|
|
"shape": "box",
|
|
"description": "default_batch_fetch_size로 프록시를 모으는 주체",
|
|
"evidence": [
|
|
{
|
|
"start_line": 1010,
|
|
"end_line": 1012
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "feed-items",
|
|
"label": "feed_items",
|
|
"kind": "store",
|
|
"role": "participant",
|
|
"shape": "cylinder",
|
|
"description": "부모 테이블",
|
|
"evidence": [
|
|
{
|
|
"start_line": 1009,
|
|
"end_line": 1010
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "highlights",
|
|
"label": "highlights",
|
|
"kind": "store",
|
|
"role": "participant",
|
|
"shape": "cylinder",
|
|
"description": "자식 테이블",
|
|
"evidence": [
|
|
{
|
|
"start_line": 1010,
|
|
"end_line": 1011
|
|
}
|
|
],
|
|
"assumption": false
|
|
}
|
|
],
|
|
"edges": [
|
|
{
|
|
"id": "m1",
|
|
"from": "loader",
|
|
"to": "session",
|
|
"label": "부모 페이지 요청",
|
|
"kind": "request",
|
|
"style": "solid",
|
|
"order": 1,
|
|
"evidence": [
|
|
{
|
|
"start_line": 1009,
|
|
"end_line": 1010
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "m2",
|
|
"from": "session",
|
|
"to": "feed-items",
|
|
"label": "부모 LIMIT 페이징",
|
|
"kind": "query",
|
|
"style": "solid",
|
|
"order": 2,
|
|
"evidence": [
|
|
{
|
|
"start_line": 1009,
|
|
"end_line": 1010
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "m3",
|
|
"from": "feed-items",
|
|
"to": "session",
|
|
"label": "페이지 부모 + 미초기화 프록시",
|
|
"kind": "response",
|
|
"style": "dashed",
|
|
"order": 3,
|
|
"evidence": [
|
|
{
|
|
"start_line": 1010,
|
|
"end_line": 1012
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "m4",
|
|
"from": "session",
|
|
"to": "highlights",
|
|
"label": "WHERE fk IN (?,…) 배치",
|
|
"kind": "query",
|
|
"style": "solid",
|
|
"order": 4,
|
|
"evidence": [
|
|
{
|
|
"start_line": 1010,
|
|
"end_line": 1012
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "m5",
|
|
"from": "highlights",
|
|
"to": "session",
|
|
"label": "자식 행",
|
|
"kind": "response",
|
|
"style": "dashed",
|
|
"order": 5,
|
|
"evidence": [
|
|
{
|
|
"start_line": 1010,
|
|
"end_line": 1011
|
|
}
|
|
],
|
|
"assumption": false
|
|
},
|
|
{
|
|
"id": "m6",
|
|
"from": "session",
|
|
"to": "loader",
|
|
"label": "부모 + 컬렉션",
|
|
"kind": "response",
|
|
"style": "dashed",
|
|
"order": 6,
|
|
"evidence": [
|
|
{
|
|
"start_line": 1012,
|
|
"end_line": 1014
|
|
}
|
|
],
|
|
"assumption": false
|
|
}
|
|
],
|
|
"legend": [],
|
|
"metadata": {
|
|
"rationale": "fetch join이 한 결과에 합쳐 LIMIT을 막았던 것과 달리 배치는 두 번에 나눈다. 그 나눔이 순서로만 드러나므로 sequence를 쓴다."
|
|
},
|
|
"source_context": {
|
|
"document": "docs/n+1liner/final/document.md",
|
|
"document_sha256": "385ca44db5bf763cb1ff28a67d531d68876402b35d21dc54f2bc702e8bda0053",
|
|
"anchor": {
|
|
"kind": "heading",
|
|
"value": "11.5 배치가 N+1과 페이징을 함께 해결하는 이유",
|
|
"line": 1007
|
|
}
|
|
},
|
|
"id": "batch-fetch-in-clause"
|
|
} |