Files
document-haness/docs/n+1liner/final/.techviz/batch-fetch-in-clause/spec.json
T

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"
}