-- L16 (b) UNION decompose — 3 visibility branches, each index-ordered, Merge Append + Hash Join -- FeedVisibilityIT.l16ExplainThreeWayPlanCompare (seed 2000, viewer user008) -- (public branch) UNION ALL (mentioned branch: JOIN feed_item_mentions) UNION ALL (private branch: partial idx) -- ORDER BY first_highlighted_at DESC, id DESC LIMIT 20 -- 읽기 포인트: Merge Append 가 미리 정렬된 분기 스트림을 병합(전체 재정렬 없음). 멘션 EXISTS 가 Hash Join(집합 기반) -- 으로, private 는 Index Only Scan(partial)+Incremental Sort 로. 구조는 우수하나 buffers 200(분기별 스캔). Limit (cost=97.16..97.40 rows=13 width=24) (actual time=0.655..0.661 rows=20 loops=1) Buffers: shared hit=200 -> Merge Append (cost=97.16..97.40 rows=13 width=24) (actual time=0.654..0.659 rows=20 loops=1) Sort Key: fi.first_highlighted_at DESC, fi.id DESC Buffers: shared hit=200 -> Limit (rows=17) -- public branch -> Sort (top-N heapsort) -> Bitmap Heap Scan on feed_items fi (Recheck Cond: visibility='PUBLIC') -> Bitmap Index Scan on ix_feed_items_visibility_sort -> Limit (rows=3) -- mentioned branch: EXISTS -> Hash Join -> Sort (top-N heapsort) -> Hash Join (Hash Cond: fi_1.id = m.feed_item_id) -> Bitmap Heap Scan on feed_items fi_1 (visibility='MENTIONED') -> Hash -> Bitmap Heap Scan on feed_item_mentions m -> Bitmap Index Scan on ix_mentions_user (mentioned_user_id=:me) -> Limit (rows=2) -- private branch: partial index, index-only -> Incremental Sort (Presorted Key: fi_2.first_highlighted_at) -> Index Only Scan using ix_feed_items_private on feed_items fi_2 (user_id=:me) Heap Fetches: 21 Planning Time: 0.398 ms Execution Time: 0.780 ms