39 lines
2.6 KiB
Plaintext
Executable File
39 lines
2.6 KiB
Plaintext
Executable File
배치 IN 조회의 실행계획 (b) — 행을 곱하지 않는다 (카테시안 소멸)
|
||
출처: FeedBatchFetchIT.l5ExplainEntityPagingHasLimitAndBatchInHasNoRowMultiplication 콘솔 출력 (b)
|
||
조건: seed(100) 직후, default_batch_fetch_size=100 세션. warm buffer cache.
|
||
쿼리: EXPLAIN (ANALYZE, BUFFERS)
|
||
SELECT h.* FROM highlights h
|
||
WHERE h.feed_item_id IN (SELECT fi.id FROM feed_items fi
|
||
ORDER BY fi.first_highlighted_at DESC, fi.id ASC LIMIT 20)
|
||
(배치 페치가 페이지 부모 20개의 highlights 를 IN 한 방으로 채우는 것과 같은 shape)
|
||
|
||
Hash Semi Join (cost=72.46..317.64 rows=234 width=710) (actual time=0.295..0.541 rows=1509 loops=1)
|
||
Hash Cond: (h.feed_item_id = "ANY_subquery".id)
|
||
Buffers: shared hit=272
|
||
-> Seq Scan on highlights h (cost=0.00..236.43 rows=2343 width=710) (actual time=0.207..0.286 rows=1961 loops=1)
|
||
Buffers: shared hit=213
|
||
-> Hash (cost=72.21..72.21 rows=20 width=16) (actual time=0.084..0.085 rows=20 loops=1)
|
||
Buckets: 1024 Batches: 1 Memory Usage: 9kB
|
||
Buffers: shared hit=59
|
||
-> Subquery Scan on "ANY_subquery" (cost=71.96..72.21 rows=20 width=16) (actual time=0.077..0.080 rows=20 loops=1)
|
||
Buffers: shared hit=59
|
||
-> Limit (cost=71.96..72.01 rows=20 width=24) (actual time=0.077..0.078 rows=20 loops=1)
|
||
Buffers: shared hit=59
|
||
-> Sort (cost=71.96..72.84 rows=354 width=24) (actual time=0.076..0.077 rows=20 loops=1)
|
||
Sort Key: fi.first_highlighted_at DESC, fi.id
|
||
Sort Method: top-N heapsort Memory: 26kB
|
||
Buffers: shared hit=59
|
||
-> Seq Scan on feed_items fi (cost=0.00..62.54 rows=354 width=24) (actual time=0.053..0.059 rows=100 loops=1)
|
||
Buffers: shared hit=59
|
||
Planning:
|
||
Buffers: shared hit=28
|
||
Planning Time: 0.206 ms
|
||
Execution Time: 0.592 ms
|
||
|
||
관찰(문서 §11):
|
||
- Semi Join 이 반환하는 행 = 1509(페이지 20개 부모의 highlights). 부모 M행 × 자식 = M×K 로 곱하지 않는다.
|
||
L3 카테시안(조인이 feed_items ⋈ highlights 를 1961행으로 곱함)과 정반대 — 자식 K행만 반환(합, 곱 아님).
|
||
- 배치 페치가 하는 일이 이 shape다: 페이지 부모 키를 모아 WHERE feed_item_id IN (…) 로 한 방에 채운다.
|
||
Hibernate 는 이를 default_batch_fetch_size 만큼 쪼개 ceil(pageItems/batch) 번 발행한다.
|
||
- Buffers: read≈0 → warm buffer cache. Execution Time 0.592 ms 는 executor 내부 시간(§6.4 caveat와 동일).
|