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