Changes between Version 25 and Version 26 of OtherTopics


Ignore:
Timestamp:
08/24/26 17:28:28 (13 days ago)
Author:
211099
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • OtherTopics

    v25 v26  
    2020        u.user_id,
    2121        u.username AS writer,
    22         st.status,
     22        s.status,
    2323        COUNT(DISTINCT ch.chapter_id) AS total_chapters,
    2424        COALESCE(SUM(ch.view_count), 0) AS total_views,
     
    3232    FROM story s
    3333    JOIN writer w   ON s.user_id = w.user_id
    34     JOIN users u    ON w.user_id = u.user_id
    35     JOIN status st  ON s.story_id = st.story_id
    36     LEFT JOIN chapter ch         ON s.story_id = ch.story_id
    37     LEFT JOIN likes l            ON s.story_id = l.story_id
    38     LEFT JOIN comment c          ON s.story_id = c.story_id
    39     LEFT JOIN collaboration col  ON s.story_id = col.story_id
    40     LEFT JOIN has_genre hg       ON s.story_id = hg.story_id
     34    JOIN users u   ON w.user_id  = u.user_id
     35    LEFT JOIN chapter ch  ON s.story_id = ch.story_id
     36    LEFT JOIN likes l   ON s.story_id  = l.story_id
     37    LEFT JOIN comment c   ON s.story_id  = c.story_id
     38    LEFT JOIN collaboration col ON s.story_id  = col.story_id
     39    LEFT JOIN has_genre hg  ON s.story_id  = hg.story_id
    4140    LEFT JOIN reading_list_items rli ON s.story_id = rli.story_id
    4241    GROUP BY
    4342        DATE_TRUNC('quarter', s.story_created_at),
    4443        s.story_id, s.short_description, s.mature_content,
    45         u.user_id, u.username, st.status
     44        u.user_id, u.username, s.status
    4645),
    4746with_engagement AS (
    48     SELECT *,
    49         ROUND((total_likes + total_comments)::DECIMAL / NULLIF(total_views, 0) * 100, 2) AS engagement_rate,
    50         ROUND(total_views::DECIMAL / NULLIF(total_chapters, 0), 2) AS avg_views_per_chapter,
    51         LAG(total_views)    OVER (PARTITION BY story_id ORDER BY quarter) AS prev_quarter_views,
    52         LAG(total_likes)    OVER (PARTITION BY story_id ORDER BY quarter) AS prev_quarter_likes,
    53         LAG(total_comments) OVER (PARTITION BY story_id ORDER BY quarter) AS prev_quarter_comments
     47    SELECT
     48        *,
     49        ROUND(
     50            (total_likes + total_comments)::DECIMAL
     51            / NULLIF(total_views, 0) * 100, 2
     52        ) AS engagement_rate,
     53        ROUND(
     54            total_views::DECIMAL
     55            / NULLIF(total_chapters, 0), 2
     56        ) AS avg_views_per_chapter,
     57        LAG(total_views) OVER (PARTITION BY story_id ORDER BY quarter)  AS prev_quarter_views,
     58        LAG(total_likes)OVER (PARTITION BY story_id ORDER BY quarter)  AS prev_quarter_likes,
     59        LAG(total_comments) OVER (PARTITION BY story_id ORDER BY quarter)  AS prev_quarter_comments
    5460    FROM quarterly_story_stats
    5561),
    5662with_growth AS (
    57     SELECT *,
    58         ROUND((total_views    - prev_quarter_views)::DECIMAL    / NULLIF(prev_quarter_views, 0)    * 100, 2) AS views_growth_pct,
    59         ROUND((total_likes    - prev_quarter_likes)::DECIMAL    / NULLIF(prev_quarter_likes, 0)    * 100, 2) AS likes_growth_pct,
    60         ROUND((total_comments - prev_quarter_comments)::DECIMAL / NULLIF(prev_quarter_comments, 0) * 100, 2) AS comments_growth_pct
     63    SELECT
     64        *,
     65        ROUND(
     66            (total_views - prev_quarter_views)::DECIMAL
     67            / NULLIF(prev_quarter_views, 0) * 100, 2
     68        )  AS views_growth_pct,
     69        ROUND(
     70            (total_likes - prev_quarter_likes)::DECIMAL
     71            / NULLIF(prev_quarter_likes, 0) * 100, 2
     72        )  AS likes_growth_pct,
     73        ROUND(
     74            (total_comments - prev_quarter_comments)::DECIMAL
     75            / NULLIF(prev_quarter_comments, 0) * 100, 2
     76        ) AS comments_growth_pct
    6177    FROM with_engagement
    6278)
     
    7591    total_views,
    7692    avg_views_per_chapter,
    77     COALESCE(views_growth_pct, 0)    AS views_growth_pct,
     93    COALESCE(views_growth_pct, 0) AS views_growth_pct,
    7894    total_likes,
    79     COALESCE(likes_growth_pct, 0)    AS likes_growth_pct,
     95    COALESCE(likes_growth_pct, 0) AS likes_growth_pct,
    8096    total_comments,
    8197    COALESCE(comments_growth_pct, 0) AS comments_growth_pct,
    82     COALESCE(avg_rating, 0)          AS avg_rating,
    83     COALESCE(engagement_rate, 0)     AS engagement_rate,
    84     RANK() OVER (PARTITION BY quarter ORDER BY total_views DESC)      AS rank_by_views,
    85     RANK() OVER (PARTITION BY quarter ORDER BY engagement_rate DESC)  AS rank_by_engagement,
    86     RANK() OVER (PARTITION BY quarter ORDER BY avg_rating DESC)       AS rank_by_rating
     98    COALESCE(avg_rating, 0) AS avg_rating,
     99    COALESCE(engagement_rate, 0) AS engagement_rate,
     100    RANK() OVER (
     101        PARTITION BY quarter
     102        ORDER BY total_views DESC
     103    ) AS rank_by_views,
     104    RANK() OVER (
     105        PARTITION BY quarter
     106        ORDER BY engagement_rate DESC
     107    ) AS rank_by_engagement,
     108    RANK() OVER (
     109        PARTITION BY quarter
     110        ORDER BY avg_rating DESC
     111    ) AS rank_by_rating
    87112FROM with_growth
    88113ORDER BY quarter DESC, rank_by_views;
    89114}}}
    90115{{{
    91 |QUERY PLAN                                                                                                                                                                                                                                                |
    92 |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    93 |Sort  (cost=3720.58..3723.08 rows=1000 width=486) (actual time=71.545..71.555 rows=50 loops=1)                                                                                                                                                            |
    94 |  Sort Key: with_engagement.quarter DESC, (rank() OVER (?))                                                                                                                                                                                               |
    95 |  Sort Method: quicksort  Memory: 38kB                                                                                                                                                                                                                    |
    96 |  ->  WindowAgg  (cost=3505.27..3670.75 rows=1000 width=486) (actual time=71.359..71.463 rows=50 loops=1)                                                                                                                                                 |
    97 |        ->  Incremental Sort  (cost=3505.16..3598.25 rows=1000 width=310) (actual time=71.348..71.383 rows=50 loops=1)                                                                                                                                    |
    98 |              Sort Key: with_engagement.quarter, with_engagement.total_views DESC                                                                                                                                                                         |
    99 |              Presorted Key: with_engagement.quarter                                                                                                                                                                                                      |
    100 |              Full-sort Groups: 2  Sort Method: quicksort  Average Memory: 32kB  Peak Memory: 32kB                                                                                                                                                        |
    101 |              ->  WindowAgg  (cost=3504.78..3570.14 rows=1000 width=310) (actual time=71.263..71.339 rows=50 loops=1)                                                                                                                                     |
    102 |                    ->  Incremental Sort  (cost=3504.71..3552.64 rows=1000 width=302) (actual time=71.260..71.294 rows=50 loops=1)                                                                                                                        |
    103 |                          Sort Key: with_engagement.quarter, with_engagement.engagement_rate DESC                                                                                                                                                         |
    104 |                          Presorted Key: with_engagement.quarter                                                                                                                                                                                          |
    105 |                          Full-sort Groups: 2  Sort Method: quicksort  Average Memory: 32kB  Peak Memory: 32kB                                                                                                                                            |
    106 |                          ->  WindowAgg  (cost=3504.55..3524.53 rows=1000 width=302) (actual time=71.199..71.254 rows=50 loops=1)                                                                                                                         |
    107 |                                ->  Sort  (cost=3504.53..3507.03 rows=1000 width=294) (actual time=71.196..71.205 rows=50 loops=1)                                                                                                                        |
    108 |                                      Sort Key: with_engagement.quarter, with_engagement.avg_rating DESC                                                                                                                                                  |
    109 |                                      Sort Method: quicksort  Memory: 35kB                                                                                                                                                                                |
    110 |                                      ->  Subquery Scan on with_engagement  (cost=100.81..3454.70 rows=1000 width=294) (actual time=47.476..71.153 rows=50 loops=1)                                                                                       |
    111 |                                            ->  WindowAgg  (cost=100.81..3444.70 rows=1000 width=298) (actual time=47.475..71.142 rows=50 loops=1)                                                                                                        |
    112 |                                                  ->  Incremental Sort  (cost=97.49..3392.20 rows=1000 width=206) (actual time=47.464..71.031 rows=50 loops=1)                                                                                            |
    113 |                                                        Sort Key: quarterly_story_stats.story_id, quarterly_story_stats.quarter                                                                                                                           |
    114 |                                                        Presorted Key: quarterly_story_stats.story_id                                                                                                                                                     |
    115 |                                                        Full-sort Groups: 2  Sort Method: quicksort  Average Memory: 31kB  Peak Memory: 31kB                                                                                                              |
    116 |                                                        ->  Subquery Scan on quarterly_story_stats  (cost=81.02..3364.10 rows=1000 width=206) (actual time=1.962..70.982 rows=50 loops=1)                                                                 |
    117 |                                                              ->  GroupAggregate  (cost=81.02..3354.10 rows=1000 width=210) (actual time=1.961..70.960 rows=50 loops=1)                                                                                   |
    118 |                                                                    Group Key: s.story_id, st.status, (date_trunc('quarter'::text, s.story_created_at)), u.user_id                                                                                        |
    119 |                                                                    ->  Incremental Sort  (cost=81.02..2405.34 rows=28654 width=153) (actual time=1.178..52.207 rows=31539 loops=1)                                                                       |
    120 |                                                                          Sort Key: s.story_id, st.status, (date_trunc('quarter'::text, s.story_created_at)), u.user_id, ch.chapter_id                                                                    |
    121 |                                                                          Presorted Key: s.story_id, st.status                                                                                                                                            |
    122 |                                                                          Full-sort Groups: 49  Sort Method: quicksort  Average Memory: 38kB  Peak Memory: 38kB                                                                                           |
    123 |                                                                          Pre-sorted Groups: 50  Sort Method: quicksort  Average Memory: 255kB  Peak Memory: 272kB                                                                                        |
    124 |                                                                          ->  Merge Left Join  (cost=61.18..875.71 rows=28654 width=153) (actual time=0.524..23.446 rows=31539 loops=1)                                                                   |
    125 |                                                                                Merge Cond: (s.story_id = hg.story_id)                                                                                                                                    |
    126 |                                                                                ->  Merge Left Join  (cost=61.03..336.01 rows=9551 width=149) (actual time=0.498..5.824 rows=10513 loops=1)                                                               |
    127 |                                                                                      Merge Cond: (s.story_id = rli.story_id)                                                                                                                             |
    128 |                                                                                      ->  Merge Left Join  (cost=56.11..174.84 rows=5191 width=145) (actual time=0.457..2.666 rows=5520 loops=1)                                                          |
    129 |                                                                                            Merge Cond: (s.story_id = l.story_id)                                                                                                                         |
    130 |                                                                                            ->  Merge Left Join  (cost=39.47..78.01 rows=902 width=141) (actual time=0.365..1.020 rows=928 loops=1)                                                       |
    131 |                                                                                                  Merge Cond: (s.story_id = ch.story_id)                                                                                                                  |
    132 |                                                                                                  ->  Merge Left Join  (cost=20.80..45.34 rows=191 width=122) (actual time=0.229..0.541 rows=192 loops=1)                                                 |
    133 |                                                                                                        Merge Cond: (s.story_id = c.story_id)                                                                                                             |
    134 |                                                                                                        ->  Merge Left Join  (cost=8.66..30.20 rows=50 width=118) (actual time=0.156..0.376 rows=51 loops=1)                                              |
    135 |                                                                                                              Merge Cond: (s.story_id = col.story_id)                                                                                                     |
    136 |                                                                                                              ->  Nested Loop  (cost=7.63..29.01 rows=50 width=114) (actual time=0.139..0.341 rows=50 loops=1)                                            |
    137 |                                                                                                                    ->  Merge Join  (cost=7.46..21.09 rows=50 width=118) (actual time=0.123..0.230 rows=50 loops=1)                                       |
    138 |                                                                                                                          Merge Cond: (st.story_id = s.story_id)                                                                                          |
    139 |                                                                                                                          ->  Index Only Scan using status_pk on status st  (cost=0.14..12.89 rows=50 width=13) (actual time=0.012..0.064 rows=50 loops=1)|
    140 |                                                                                                                                Heap Fetches: 50                                                                                                          |
    141 |                                                                                                                          ->  Sort  (cost=7.32..7.45 rows=50 width=109) (actual time=0.108..0.117 rows=50 loops=1)                                        |
    142 |                                                                                                                                Sort Key: s.story_id                                                                                                      |
    143 |                                                                                                                                Sort Method: quicksort  Memory: 31kB                                                                                      |
    144 |                                                                                                                                ->  Hash Join  (cost=1.23..5.91 rows=50 width=109) (actual time=0.054..0.088 rows=50 loops=1)                             |
    145 |                                                                                                                                      Hash Cond: (s.user_id = u.user_id)                                                                                  |
    146 |                                                                                                                                      ->  Seq Scan on story s  (cost=0.00..4.50 rows=50 width=92) (actual time=0.025..0.035 rows=50 loops=1)              |
    147 |                                                                                                                                      ->  Hash  (cost=1.10..1.10 rows=10 width=17) (actual time=0.016..0.017 rows=10 loops=1)                             |
    148 |                                                                                                                                            Buckets: 1024  Batches: 1  Memory Usage: 9kB                                                                  |
    149 |                                                                                                                                            ->  Seq Scan on users u  (cost=0.00..1.10 rows=10 width=17) (actual time=0.008..0.010 rows=10 loops=1)        |
    150 |                                                                                                                    ->  Memoize  (cost=0.17..1.14 rows=1 width=4) (actual time=0.001..0.001 rows=1 loops=50)                                              |
    151 |                                                                                                                          Cache Key: s.user_id                                                                                                            |
    152 |                                                                                                                          Cache Mode: logical                                                                                                             |
    153 |                                                                                                                          Hits: 45  Misses: 5  Evictions: 0  Overflows: 0  Memory Usage: 1kB                                                              |
    154 |                                                                                                                          ->  Index Only Scan using writer_pkey on writer w  (cost=0.15..1.13 rows=1 width=4) (actual time=0.005..0.005 rows=1 loops=5)   |
    155 |                                                                                                                                Index Cond: (user_id = s.user_id)                                                                                         |
    156 |                                                                                                                                Heap Fetches: 5                                                                                                           |
    157 |                                                                                                              ->  Sort  (cost=1.03..1.03 rows=2 width=8) (actual time=0.015..0.016 rows=2 loops=1)                                                        |
    158 |                                                                                                                    Sort Key: col.story_id                                                                                                                |
    159 |                                                                                                                    Sort Method: quicksort  Memory: 25kB                                                                                                  |
    160 |                                                                                                                    ->  Seq Scan on collaboration col  (cost=0.00..1.02 rows=2 width=8) (actual time=0.009..0.010 rows=2 loops=1)                         |
    161 |                                                                                                        ->  Sort  (cost=12.15..12.62 rows=191 width=8) (actual time=0.072..0.093 rows=192 loops=1)                                                        |
    162 |                                                                                                              Sort Key: c.story_id                                                                                                                        |
    163 |                                                                                                              Sort Method: quicksort  Memory: 29kB                                                                                                        |
    164 |                                                                                                              ->  Seq Scan on comment c  (cost=0.00..4.91 rows=191 width=8) (actual time=0.011..0.043 rows=191 loops=1)                                   |
    165 |                                                                                                  ->  Sort  (cost=18.66..19.25 rows=236 width=23) (actual time=0.134..0.199 rows=925 loops=1)                                                             |
    166 |                                                                                                        Sort Key: ch.story_id                                                                                                                             |
    167 |                                                                                                        Sort Method: quicksort  Memory: 34kB                                                                                                              |
    168 |                                                                                                        ->  Seq Scan on chapter ch  (cost=0.00..9.36 rows=236 width=23) (actual time=0.009..0.076 rows=236 loops=1)                                       |
    169 |                                                                                            ->  Sort  (cost=16.64..17.36 rows=288 width=8) (actual time=0.091..0.440 rows=5501 loops=1)                                                                   |
    170 |                                                                                                  Sort Key: l.story_id                                                                                                                                    |
    171 |                                                                                                  Sort Method: quicksort  Memory: 31kB                                                                                                                    |
    172 |                                                                                                  ->  Seq Scan on likes l  (cost=0.00..4.88 rows=288 width=8) (actual time=0.014..0.049 rows=288 loops=1)                                                 |
    173 |                                                                                      ->  Sort  (cost=4.92..5.15 rows=92 width=8) (actual time=0.039..0.639 rows=9674 loops=1)                                                                            |
    174 |                                                                                            Sort Key: rli.story_id                                                                                                                                        |
    175 |                                                                                            Sort Method: quicksort  Memory: 27kB                                                                                                                          |
    176 |                                                                                            ->  Seq Scan on reading_list_items rli  (cost=0.00..1.92 rows=92 width=8) (actual time=0.008..0.019 rows=92 loops=1)                                          |
    177 |                                                                                ->  Materialize  (cost=0.14..14.77 rows=150 width=8) (actual time=0.018..1.851 rows=31300 loops=1)                                                                        |
    178 |                                                                                      ->  Index Only Scan using has_genre_pk on has_genre hg  (cost=0.14..14.39 rows=150 width=8) (actual time=0.016..0.111 rows=150 loops=1)                             |
    179 |                                                                                            Heap Fetches: 150                                                                                                                                             |
    180 |Planning Time: 6.234 ms                                                                                                                                                                                                                                   |
    181 |Execution Time: 71.861 ms                                                                                                                                                                                                                                 |
    182 }}}
    183 Average time without indexes is: 72.384 ms
     116| QUERY PLAN |
     117| :--- |
     118| Sort  \(cost=11491685270.39..11491685274.39 rows=1600 width=1539\) \(actual time=1.816..1.822 rows=5 loops=1\) |
     119|   Sort Key: with\_engagement.quarter DESC, \(rank\(\) OVER \(?\)\) |
     120|   Sort Method: quicksort  Memory: 26kB |
     121|   ->  WindowAgg  \(cost=11491684914.18..11491685185.24 rows=1600 width=1539\) \(actual time=1.800..1.813 rows=5 loops=1\) |
     122|         ->  Incremental Sort  \(cost=11491684914.18..11491685069.24 rows=1600 width=1363\) \(actual time=1.785..1.792 rows=5 loops=1\) |
     123|               Sort Key: with\_engagement.quarter, with\_engagement.total\_views DESC |
     124|               Presorted Key: with\_engagement.quarter |
     125|               Full-sort Groups: 1  Sort Method: quicksort  Average Memory: 26kB  Peak Memory: 26kB |
     126|               ->  WindowAgg  \(cost=11491684913.52..11491685021.24 rows=1600 width=1363\) \(actual time=1.775..1.786 rows=5 loops=1\) |
     127|                     ->  Incremental Sort  \(cost=11491684913.52..11491684993.24 rows=1600 width=1355\) \(actual time=1.773..1.780 rows=5 loops=1\) |
     128|                           Sort Key: with\_engagement.quarter, with\_engagement.engagement\_rate DESC |
     129|                           Presorted Key: with\_engagement.quarter |
     130|                           Full-sort Groups: 1  Sort Method: quicksort  Average Memory: 26kB  Peak Memory: 26kB |
     131|                           ->  WindowAgg  \(cost=11491684913.24..11491684945.24 rows=1600 width=1355\) \(actual time=1.761..1.773 rows=5 loops=1\) |
     132|                                 ->  Sort  \(cost=11491684913.24..11491684917.24 rows=1600 width=1347\) \(actual time=1.758..1.765 rows=5 loops=1\) |
     133|                                       Sort Key: with\_engagement.quarter, with\_engagement.avg\_rating DESC |
     134|                                       Sort Method: quicksort  Memory: 26kB |
     135|                                       ->  Subquery Scan on with\_engagement  \(cost=11491684724.09..11491684828.09 rows=1600 width=1347\) \(actual time=1.744..1.758 rows=5 loops=1\) |
     136|                                             ->  WindowAgg  \(cost=11491684724.09..11491684812.09 rows=1600 width=1351\) \(actual time=1.743..1.756 rows=5 loops=1\) |
     137|                                                   ->  Sort  \(cost=11491684724.09..11491684728.09 rows=1600 width=1259\) \(actual time=1.732..1.738 rows=5 loops=1\) |
     138|                                                         Sort Key: quarterly\_story\_stats.story\_id, quarterly\_story\_stats.quarter |
     139|                                                         Sort Method: quicksort  Memory: 25kB |
     140|                                                         ->  Subquery Scan on quarterly\_story\_stats  \(cost=11381017300.90..11491684638.94 rows=1600 width=1259\) \(actual time=1.473..1.733 rows=5 loops=1\) |
     141|                                                               ->  GroupAggregate  \(cost=11381017300.90..11491684622.94 rows=1600 width=1263\) \(actual time=1.472..1.731 rows=5 loops=1\) |
     142|                                                                     Group Key: \(date\_trunc\('quarter'::text, s.story\_created\_at\)\), s.story\_id, u.user\_id |
     143|                                                                     ->  Sort  \(cost=11381017300.90..11389530169.67 rows=3405147509 width=1211\) \(actual time=1.237..1.274 rows=939 loops=1\) |
     144|                                                                           Sort Key: \(date\_trunc\('quarter'::text, s.story\_created\_at\)\), s.story\_id, u.user\_id, ch.chapter\_id |
     145|                                                                           Sort Method: quicksort  Memory: 195kB |
     146|                                                                           ->  Nested Loop Left Join  \(cost=96.66..17916485.18 rows=3405147509 width=1211\) \(actual time=0.184..0.706 rows=939 loops=1\) |
     147|                                                                                 ->  Nested Loop Left Join  \(cost=96.50..199887.04 rows=73624811 width=1207\) \(actual time=0.170..0.331 rows=360 loops=1\) |
     148|                                                                                       ->  Nested Loop Left Join  \(cost=96.33..4359.52 rows=1303094 width=1203\) \(actual time=0.160..0.218 rows=120 loops=1\) |
     149|                                                                                             ->  Hash Right Join  \(cost=96.17..209.67 rows=28175 width=1199\) \(actual time=0.148..0.166 rows=28 loops=1\) |
     150|                                                                                                   Hash Cond: \(c.story\_id = s.story\_id\) |
     151|                                                                                                   ->  Seq Scan on comment c  \(cost=0.00..19.20 rows=920 width=8\) \(actual time=0.006..0.008 rows=11 loops=1\) |
     152|                                                                                                   ->  Hash  \(cost=80.86..80.86 rows=1225 width=1195\) \(actual time=0.134..0.138 rows=12 loops=1\) |
     153|                                                                                                         Buckets: 2048  Batches: 1  Memory Usage: 18kB |
     154|                                                                                                         ->  Hash Right Join  \(cost=61.06..80.86 rows=1225 width=1195\) \(actual time=0.124..0.132 rows=12 loops=1\) |
     155|                                                                                                               Hash Cond: \(col.story\_id = s.story\_id\) |
     156|                                                                                                               ->  Seq Scan on collaboration col  \(cost=0.00..14.90 rows=490 width=8\) \(actual time=0.006..0.006 rows=2 loops=1\) |
     157|                                                                                                               ->  Hash  \(cost=59.81..59.81 rows=100 width=1191\) \(actual time=0.111..0.114 rows=11 loops=1\) |
     158|                                                                                                                     Buckets: 1024  Batches: 1  Memory Usage: 10kB |
     159|                                                                                                                     ->  Hash Left Join  \(cost=23.29..59.81 rows=100 width=1191\) \(actual time=0.094..0.105 rows=11 loops=1\) |
     160|                                                                                                                           Hash Cond: \(s.story\_id = ch.story\_id\) |
     161|                                                                                                                           ->  Nested Loop  \(cost=11.04..47.01 rows=40 width=1167\) \(actual time=0.072..0.080 rows=5 loops=1\) |
     162|                                                                                                                                 Join Filter: \(u.user\_id = s.user\_id\) |
     163|                                                                                                                                 ->  Hash Join  \(cost=10.90..38.76 rows=40 width=655\) \(actual time=0.053..0.057 rows=5 loops=1\) |
     164|                                                                                                                                       Hash Cond: \(w.user\_id = s.user\_id\) |
     165|                                                                                                                                       ->  Seq Scan on writer w  \(cost=0.00..22.70 rows=1270 width=4\) \(actual time=0.029..0.030 rows=5 loops=1\) |
     166|                                                                                                                                       ->  Hash  \(cost=10.40..10.40 rows=40 width=651\) \(actual time=0.015..0.015 rows=5 loops=1\) |
     167|                                                                                                                                             Buckets: 1024  Batches: 1  Memory Usage: 9kB |
     168|                                                                                                                                             ->  Seq Scan on story s  \(cost=0.00..10.40 rows=40 width=651\) \(actual time=0.007..0.008 rows=5 loops=1\) |
     169|                                                                                                                                 ->  Index Scan using users\_pkey on users u  \(cost=0.14..0.20 rows=1 width=520\) \(actual time=0.004..0.004 rows=1 loops=5\) |
     170|                                                                                                                                       Index Cond: \(user\_id = w.user\_id\) |
     171|                                                                                                                           ->  Hash  \(cost=11.00..11.00 rows=100 width=28\) \(actual time=0.015..0.015 rows=11 loops=1\) |
     172|                                                                                                                                 Buckets: 1024  Batches: 1  Memory Usage: 9kB |
     173|                                                                                                                                 ->  Seq Scan on chapter ch  \(cost=0.00..11.00 rows=100 width=28\) \(actual time=0.008..0.011 rows=11 loops=1\) |
     174|                                                                                             ->  Memoize  \(cost=0.16..15.33 rows=9 width=8\) \(actual time=0.001..0.001 rows=4 loops=28\) |
     175|                                                                                                   Cache Key: s.story\_id |
     176|                                                                                                   Cache Mode: logical |
     177|                                                                                                   Hits: 23  Misses: 5  Evictions: 0  Overflows: 0  Memory Usage: 2kB |
     178|                                                                                                   ->  Index Only Scan using like\_pk on likes l  \(cost=0.15..15.32 rows=9 width=8\) \(actual time=0.003..0.004 rows=4 loops=5\) |
     179|                                                                                                         Index Cond: \(story\_id = s.story\_id\) |
     180|                                                                                                         Heap Fetches: 18 |
     181|                                                                                       ->  Memoize  \(cost=0.17..1.56 rows=11 width=8\) \(actual time=0.000..0.000 rows=3 loops=120\) |
     182|                                                                                             Cache Key: s.story\_id |
     183|                                                                                             Cache Mode: logical |
     184|                                                                                             Hits: 115  Misses: 5  Evictions: 0  Overflows: 0  Memory Usage: 1kB |
     185|                                                                                             ->  Index Only Scan using has\_genre\_pk on has\_genre hg  \(cost=0.15..1.55 rows=11 width=8\) \(actual time=0.002..0.003 rows=3 loops=5\) |
     186|                                                                                                   Index Cond: \(story\_id = s.story\_id\) |
     187|                                                                                                   Heap Fetches: 15 |
     188|                                                                                 ->  Memoize  \(cost=0.16..15.33 rows=9 width=8\) \(actual time=0.000..0.000 rows=3 loops=360\) |
     189|                                                                                       Cache Key: s.story\_id |
     190|                                                                                       Cache Mode: logical |
     191|                                                                                       Hits: 355  Misses: 5  Evictions: 0  Overflows: 0  Memory Usage: 1kB |
     192|                                                                                       ->  Index Only Scan using reading\_list\_items\_pk on reading\_list\_items rli  \(cost=0.15..15.32 rows=9 width=8\) \(actual time=0.002..0.003 rows=3 loops=5\) |
     193|                                                                                             Index Cond: \(story\_id = s.story\_id\) |
     194|                                                                                             Heap Fetches: 13 |
     195| Planning Time: 4.031 ms |
     196| Execution Time: 2.159 ms |
     197}}}
     198Average time without indexes is: 4.49 ms
    184199=== Indexes for this queries
    185200{{{
     
    215230ANALYZE has_genre;
    216231ANALYZE reading_list_items;
    217 ANALYZE status;
    218232ANALYZE users;
    219233}}}
    220234{{{
    221 |QUERY PLAN                                                                                                                                                                                                                                                |
    222 |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    223 |Sort  (cost=3720.58..3723.08 rows=1000 width=486) (actual time=74.567..74.583 rows=50 loops=1)                                                                                                                                                            |
    224 |  Sort Key: with_engagement.quarter DESC, (rank() OVER (?))                                                                                                                                                                                               |
    225 |  Sort Method: quicksort  Memory: 38kB                                                                                                                                                                                                                    |
    226 |  ->  WindowAgg  (cost=3505.27..3670.75 rows=1000 width=486) (actual time=74.380..74.490 rows=50 loops=1)                                                                                                                                                 |
    227 |        ->  Incremental Sort  (cost=3505.16..3598.25 rows=1000 width=310) (actual time=74.364..74.404 rows=50 loops=1)                                                                                                                                    |
    228 |              Sort Key: with_engagement.quarter, with_engagement.total_views DESC                                                                                                                                                                         |
    229 |              Presorted Key: with_engagement.quarter                                                                                                                                                                                                      |
    230 |              Full-sort Groups: 2  Sort Method: quicksort  Average Memory: 32kB  Peak Memory: 32kB                                                                                                                                                        |
    231 |              ->  WindowAgg  (cost=3504.78..3570.14 rows=1000 width=310) (actual time=74.278..74.359 rows=50 loops=1)                                                                                                                                     |
    232 |                    ->  Incremental Sort  (cost=3504.71..3552.64 rows=1000 width=302) (actual time=74.274..74.311 rows=50 loops=1)                                                                                                                        |
    233 |                          Sort Key: with_engagement.quarter, with_engagement.engagement_rate DESC                                                                                                                                                         |
    234 |                          Presorted Key: with_engagement.quarter                                                                                                                                                                                          |
    235 |                          Full-sort Groups: 2  Sort Method: quicksort  Average Memory: 32kB  Peak Memory: 32kB                                                                                                                                            |
    236 |                          ->  WindowAgg  (cost=3504.55..3524.53 rows=1000 width=302) (actual time=74.209..74.271 rows=50 loops=1)                                                                                                                         |
    237 |                                ->  Sort  (cost=3504.53..3507.03 rows=1000 width=294) (actual time=74.202..74.216 rows=50 loops=1)                                                                                                                        |
    238 |                                      Sort Key: with_engagement.quarter, with_engagement.avg_rating DESC                                                                                                                                                  |
    239 |                                      Sort Method: quicksort  Memory: 35kB                                                                                                                                                                                |
    240 |                                      ->  Subquery Scan on with_engagement  (cost=100.81..3454.70 rows=1000 width=294) (actual time=49.439..74.159 rows=50 loops=1)                                                                                       |
    241 |                                            ->  WindowAgg  (cost=100.81..3444.70 rows=1000 width=298) (actual time=49.437..74.147 rows=50 loops=1)                                                                                                        |
    242 |                                                  ->  Incremental Sort  (cost=97.49..3392.20 rows=1000 width=206) (actual time=49.423..74.026 rows=50 loops=1)                                                                                            |
    243 |                                                        Sort Key: quarterly_story_stats.story_id, quarterly_story_stats.quarter                                                                                                                           |
    244 |                                                        Presorted Key: quarterly_story_stats.story_id                                                                                                                                                     |
    245 |                                                        Full-sort Groups: 2  Sort Method: quicksort  Average Memory: 31kB  Peak Memory: 31kB                                                                                                              |
    246 |                                                        ->  Subquery Scan on quarterly_story_stats  (cost=81.02..3364.10 rows=1000 width=206) (actual time=2.134..73.965 rows=50 loops=1)                                                                 |
    247 |                                                              ->  GroupAggregate  (cost=81.02..3354.10 rows=1000 width=210) (actual time=2.133..73.936 rows=50 loops=1)                                                                                   |
    248 |                                                                    Group Key: s.story_id, st.status, (date_trunc('quarter'::text, s.story_created_at)), u.user_id                                                                                        |
    249 |                                                                    ->  Incremental Sort  (cost=81.02..2405.34 rows=28654 width=153) (actual time=1.210..53.754 rows=31539 loops=1)                                                                       |
    250 |                                                                          Sort Key: s.story_id, st.status, (date_trunc('quarter'::text, s.story_created_at)), u.user_id, ch.chapter_id                                                                    |
    251 |                                                                          Presorted Key: s.story_id, st.status                                                                                                                                            |
    252 |                                                                          Full-sort Groups: 49  Sort Method: quicksort  Average Memory: 38kB  Peak Memory: 38kB                                                                                           |
    253 |                                                                          Pre-sorted Groups: 50  Sort Method: quicksort  Average Memory: 255kB  Peak Memory: 272kB                                                                                        |
    254 |                                                                          ->  Merge Left Join  (cost=61.18..875.71 rows=28654 width=153) (actual time=0.533..24.135 rows=31539 loops=1)                                                                   |
    255 |                                                                                Merge Cond: (s.story_id = hg.story_id)                                                                                                                                    |
    256 |                                                                                ->  Merge Left Join  (cost=61.03..336.01 rows=9551 width=149) (actual time=0.507..6.219 rows=10513 loops=1)                                                               |
    257 |                                                                                      Merge Cond: (s.story_id = rli.story_id)                                                                                                                             |
    258 |                                                                                      ->  Merge Left Join  (cost=56.11..174.84 rows=5191 width=145) (actual time=0.467..2.947 rows=5520 loops=1)                                                          |
    259 |                                                                                            Merge Cond: (s.story_id = l.story_id)                                                                                                                         |
    260 |                                                                                            ->  Merge Left Join  (cost=39.47..78.01 rows=902 width=141) (actual time=0.374..1.145 rows=928 loops=1)                                                       |
    261 |                                                                                                  Merge Cond: (s.story_id = ch.story_id)                                                                                                                  |
    262 |                                                                                                  ->  Merge Left Join  (cost=20.80..45.34 rows=191 width=122) (actual time=0.240..0.645 rows=192 loops=1)                                                 |
    263 |                                                                                                        Merge Cond: (s.story_id = c.story_id)                                                                                                             |
    264 |                                                                                                        ->  Merge Left Join  (cost=8.66..30.20 rows=50 width=118) (actual time=0.167..0.471 rows=51 loops=1)                                              |
    265 |                                                                                                              Merge Cond: (s.story_id = col.story_id)                                                                                                     |
    266 |                                                                                                              ->  Nested Loop  (cost=7.63..29.01 rows=50 width=114) (actual time=0.150..0.432 rows=50 loops=1)                                            |
    267 |                                                                                                                    ->  Merge Join  (cost=7.46..21.09 rows=50 width=118) (actual time=0.133..0.291 rows=50 loops=1)                                       |
    268 |                                                                                                                          Merge Cond: (st.story_id = s.story_id)                                                                                          |
    269 |                                                                                                                          ->  Index Only Scan using status_pk on status st  (cost=0.14..12.89 rows=50 width=13) (actual time=0.013..0.102 rows=50 loops=1)|
    270 |                                                                                                                                Heap Fetches: 50                                                                                                          |
    271 |                                                                                                                          ->  Sort  (cost=7.32..7.45 rows=50 width=109) (actual time=0.116..0.130 rows=50 loops=1)                                        |
    272 |                                                                                                                                Sort Key: s.story_id                                                                                                      |
    273 |                                                                                                                                Sort Method: quicksort  Memory: 31kB                                                                                      |
    274 |                                                                                                                                ->  Hash Join  (cost=1.23..5.91 rows=50 width=109) (actual time=0.045..0.098 rows=50 loops=1)                             |
    275 |                                                                                                                                      Hash Cond: (s.user_id = u.user_id)                                                                                  |
    276 |                                                                                                                                      ->  Seq Scan on story s  (cost=0.00..4.50 rows=50 width=92) (actual time=0.016..0.027 rows=50 loops=1)              |
    277 |                                                                                                                                      ->  Hash  (cost=1.10..1.10 rows=10 width=17) (actual time=0.017..0.018 rows=10 loops=1)                             |
    278 |                                                                                                                                            Buckets: 1024  Batches: 1  Memory Usage: 9kB                                                                  |
    279 |                                                                                                                                            ->  Seq Scan on users u  (cost=0.00..1.10 rows=10 width=17) (actual time=0.008..0.010 rows=10 loops=1)        |
    280 |                                                                                                                    ->  Memoize  (cost=0.17..1.14 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=50)                                              |
    281 |                                                                                                                          Cache Key: s.user_id                                                                                                            |
    282 |                                                                                                                          Cache Mode: logical                                                                                                             |
    283 |                                                                                                                          Hits: 45  Misses: 5  Evictions: 0  Overflows: 0  Memory Usage: 1kB                                                              |
    284 |                                                                                                                          ->  Index Only Scan using writer_pkey on writer w  (cost=0.15..1.13 rows=1 width=4) (actual time=0.006..0.006 rows=1 loops=5)   |
    285 |                                                                                                                                Index Cond: (user_id = s.user_id)                                                                                         |
    286 |                                                                                                                                Heap Fetches: 5                                                                                                           |
    287 |                                                                                                              ->  Sort  (cost=1.03..1.03 rows=2 width=8) (actual time=0.015..0.016 rows=2 loops=1)                                                        |
    288 |                                                                                                                    Sort Key: col.story_id                                                                                                                |
    289 |                                                                                                                    Sort Method: quicksort  Memory: 25kB                                                                                                  |
    290 |                                                                                                                    ->  Seq Scan on collaboration col  (cost=0.00..1.02 rows=2 width=8) (actual time=0.009..0.010 rows=2 loops=1)                         |
    291 |                                                                                                        ->  Sort  (cost=12.15..12.62 rows=191 width=8) (actual time=0.071..0.094 rows=192 loops=1)                                                        |
    292 |                                                                                                              Sort Key: c.story_id                                                                                                                        |
    293 |                                                                                                              Sort Method: quicksort  Memory: 29kB                                                                                                        |
    294 |                                                                                                              ->  Seq Scan on comment c  (cost=0.00..4.91 rows=191 width=8) (actual time=0.011..0.043 rows=191 loops=1)                                   |
    295 |                                                                                                  ->  Sort  (cost=18.66..19.25 rows=236 width=23) (actual time=0.133..0.217 rows=925 loops=1)                                                             |
    296 |                                                                                                        Sort Key: ch.story_id                                                                                                                             |
    297 |                                                                                                        Sort Method: quicksort  Memory: 34kB                                                                                                              |
    298 |                                                                                                        ->  Seq Scan on chapter ch  (cost=0.00..9.36 rows=236 width=23) (actual time=0.009..0.077 rows=236 loops=1)                                       |
    299 |                                                                                            ->  Sort  (cost=16.64..17.36 rows=288 width=8) (actual time=0.091..0.464 rows=5501 loops=1)                                                                   |
    300 |                                                                                                  Sort Key: l.story_id                                                                                                                                    |
    301 |                                                                                                  Sort Method: quicksort  Memory: 31kB                                                                                                                    |
    302 |                                                                                                  ->  Seq Scan on likes l  (cost=0.00..4.88 rows=288 width=8) (actual time=0.013..0.049 rows=288 loops=1)                                                 |
    303 |                                                                                      ->  Sort  (cost=4.92..5.15 rows=92 width=8) (actual time=0.039..0.657 rows=9674 loops=1)                                                                            |
    304 |                                                                                            Sort Key: rli.story_id                                                                                                                                        |
    305 |                                                                                            Sort Method: quicksort  Memory: 27kB                                                                                                                          |
    306 |                                                                                            ->  Seq Scan on reading_list_items rli  (cost=0.00..1.92 rows=92 width=8) (actual time=0.007..0.019 rows=92 loops=1)                                          |
    307 |                                                                                ->  Materialize  (cost=0.14..14.77 rows=150 width=8) (actual time=0.018..1.898 rows=31300 loops=1)                                                                        |
    308 |                                                                                      ->  Index Only Scan using idx_has_genre_covering on has_genre hg  (cost=0.14..14.39 rows=150 width=8) (actual time=0.015..0.146 rows=150 loops=1)                   |
    309 |                                                                                            Heap Fetches: 150                                                                                                                                             |
    310 |Planning Time: 8.520 ms                                                                                                                                                                                                                                   |
    311 |Execution Time: 74.902 ms                                                                                                                                                                                                                                 |
    312 }}}
    313 Average time: 72.240 ms
    314 
    315 The covering indexes were created and verified across all joined tables. The average execution time is 72.384 ms without indexes and 72.240 ms with indexes. In the execution plan, idx_has_genre_covering, status_pk, and writer_pkey are used as Index Only Scans. The remaining tables use Seq Scan because Merge Left Joins require pre-sorted input, making sequential scans cheaper at this data volume. The indexes are kept as they will be automatically utilized by the planner as data volume grows.
     235| QUERY PLAN |
     236| :--- |
     237| Sort  \(cost=115.88..116.01 rows=50 width=478\) \(actual time=1.845..1.853 rows=5 loops=1\) |
     238|   Sort Key: with\_engagement.quarter DESC, \(rank\(\) OVER \(?\)\) |
     239|   Sort Method: quicksort  Memory: 26kB |
     240|   ->  WindowAgg  \(cost=104.59..114.47 rows=50 width=478\) \(actual time=1.829..1.844 rows=5 loops=1\) |
     241|         ->  Incremental Sort  \(cost=104.59..110.84 rows=50 width=302\) \(actual time=1.814..1.823 rows=5 loops=1\) |
     242|               Sort Key: with\_engagement.quarter, with\_engagement.total\_views DESC |
     243|               Presorted Key: with\_engagement.quarter |
     244|               Full-sort Groups: 1  Sort Method: quicksort  Average Memory: 26kB  Peak Memory: 26kB |
     245|               ->  WindowAgg  \(cost=104.50..108.59 rows=50 width=302\) \(actual time=1.803..1.816 rows=5 loops=1\) |
     246|                     ->  Incremental Sort  \(cost=104.50..107.72 rows=50 width=294\) \(actual time=1.801..1.809 rows=5 loops=1\) |
     247|                           Sort Key: with\_engagement.quarter, with\_engagement.engagement\_rate DESC |
     248|                           Presorted Key: with\_engagement.quarter |
     249|                           Full-sort Groups: 1  Sort Method: quicksort  Average Memory: 26kB  Peak Memory: 26kB |
     250|                           ->  WindowAgg  \(cost=104.47..105.47 rows=50 width=294\) \(actual time=1.789..1.802 rows=5 loops=1\) |
     251|                                 ->  Sort  \(cost=104.47..104.59 rows=50 width=286\) \(actual time=1.785..1.792 rows=5 loops=1\) |
     252|                                       Sort Key: with\_engagement.quarter, with\_engagement.avg\_rating DESC |
     253|                                       Sort Method: quicksort  Memory: 26kB |
     254|                                       ->  Subquery Scan on with\_engagement  \(cost=99.81..103.06 rows=50 width=286\) \(actual time=1.768..1.784 rows=5 loops=1\) |
     255|                                             ->  WindowAgg  \(cost=99.81..102.56 rows=50 width=290\) \(actual time=1.766..1.782 rows=5 loops=1\) |
     256|                                                   ->  Sort  \(cost=99.81..99.93 rows=50 width=198\) \(actual time=1.750..1.758 rows=5 loops=1\) |
     257|                                                         Sort Key: quarterly\_story\_stats.story\_id, quarterly\_story\_stats.quarter |
     258|                                                         Sort Method: quicksort  Memory: 25kB |
     259|                                                         ->  Subquery Scan on quarterly\_story\_stats  \(cost=74.73..98.40 rows=50 width=198\) \(actual time=1.463..1.752 rows=5 loops=1\) |
     260|                                                               ->  GroupAggregate  \(cost=74.73..97.90 rows=50 width=202\) \(actual time=1.463..1.750 rows=5 loops=1\) |
     261|                                                                     Group Key: \(date\_trunc\('quarter'::text, s.story\_created\_at\)\), s.story\_id, u.user\_id |
     262|                                                                     ->  Sort  \(cost=74.73..76.44 rows=686 width=145\) \(actual time=1.229..1.267 rows=939 loops=1\) |
     263|                                                                           Sort Key: \(date\_trunc\('quarter'::text, s.story\_created\_at\)\), s.story\_id, u.user\_id, ch.chapter\_id |
     264|                                                                           Sort Method: quicksort  Memory: 195kB |
     265|                                                                           ->  Hash Left Join  \(cost=7.83..42.41 rows=686 width=145\) \(actual time=0.236..0.641 rows=939 loops=1\) |
     266|                                                                                 Hash Cond: \(s.story\_id = rli.story\_id\) |
     267|                                                                                 ->  Hash Left Join  \(cost=6.54..30.89 rows=264 width=141\) \(actual time=0.218..0.335 rows=360 loops=1\) |
     268|                                                                                       Hash Cond: \(s.story\_id = l.story\_id\) |
     269|                                                                                       ->  Hash Left Join  \(cost=5.13..26.27 rows=72 width=137\) \(actual time=0.169..0.223 rows=84 loops=1\) |
     270|                                                                                             Hash Cond: \(s.story\_id = hg.story\_id\) |
     271|                                                                                             ->  Hash Left Join  \(cost=3.79..24.06 rows=24 width=133\) \(actual time=0.145..0.182 rows=28 loops=1\) |
     272|                                                                                                   Hash Cond: \(s.story\_id = c.story\_id\) |
     273|                                                                                                   ->  Hash Left Join  \(cost=2.54..22.50 rows=11 width=129\) \(actual time=0.082..0.113 rows=12 loops=1\) |
     274|                                                                                                         Hash Cond: \(s.story\_id = ch.story\_id\) |
     275|                                                                                                         ->  Nested Loop Left Join  \(cost=0.30..20.12 rows=5 width=110\) \(actual time=0.063..0.089 rows=6 loops=1\) |
     276|                                                                                                               Join Filter: \(s.story\_id = col.story\_id\) |
     277|                                                                                                               Rows Removed by Join Filter: 8 |
     278|                                                                                                               ->  Nested Loop  \(cost=0.30..18.94 rows=5 width=106\) \(actual time=0.053..0.075 rows=5 loops=1\) |
     279|                                                                                                                     Join Filter: \(s.user\_id = u.user\_id\) |
     280|                                                                                                                     ->  Nested Loop  \(cost=0.16..18.07 rows=5 width=97\) \(actual time=0.046..0.060 rows=5 loops=1\) |
     281|                                                                                                                           ->  Seq Scan on story s  \(cost=0.00..1.05 rows=5 width=93\) \(actual time=0.027..0.028 rows=5 loops=1\) |
     282|                                                                                                                           ->  Memoize  \(cost=0.16..4.98 rows=1 width=4\) \(actual time=0.005..0.005 rows=1 loops=5\) |
     283|                                                                                                                                 Cache Key: s.user\_id |
     284|                                                                                                                                 Cache Mode: logical |
     285|                                                                                                                                 Hits: 2  Misses: 3  Evictions: 0  Overflows: 0  Memory Usage: 1kB |
     286|                                                                                                                                 ->  Index Only Scan using writer\_pkey on writer w  \(cost=0.15..4.97 rows=1 width=4\) \(actual time=0.006..0.006 rows=1 loops=3\) |
     287|                                                                                                                                       Index Cond: \(user\_id = s.user\_id\) |
     288|                                                                                                                                       Heap Fetches: 3 |
     289|                                                                                                                     ->  Index Only Scan using idx\_users\_covering on users u  \(cost=0.14..0.16 rows=1 width=17\) \(actual time=0.002..0.002 rows=1 loops=5\) |
     290|                                                                                                                           Index Cond: \(user\_id = w.user\_id\) |
     291|                                                                                                                           Heap Fetches: 5 |
     292|                                                                                                               ->  Materialize  \(cost=0.00..1.03 rows=2 width=8\) \(actual time=0.002..0.002 rows=2 loops=5\) |
     293|                                                                                                                     ->  Seq Scan on collaboration col  \(cost=0.00..1.02 rows=2 width=8\) \(actual time=0.006..0.007 rows=2 loops=1\) |
     294|                                                                                                         ->  Hash  \(cost=2.11..2.11 rows=11 width=23\) \(actual time=0.014..0.015 rows=11 loops=1\) |
     295|                                                                                                               Buckets: 1024  Batches: 1  Memory Usage: 9kB |
     296|                                                                                                               ->  Seq Scan on chapter ch  \(cost=0.00..2.11 rows=11 width=23\) \(actual time=0.007..0.010 rows=11 loops=1\) |
     297|                                                                                                   ->  Hash  \(cost=1.11..1.11 rows=11 width=8\) \(actual time=0.014..0.014 rows=11 loops=1\) |
     298|                                                                                                         Buckets: 1024  Batches: 1  Memory Usage: 9kB |
     299|                                                                                                         ->  Seq Scan on comment c  \(cost=0.00..1.11 rows=11 width=8\) \(actual time=0.009..0.010 rows=11 loops=1\) |
     300|                                                                                             ->  Hash  \(cost=1.15..1.15 rows=15 width=8\) \(actual time=0.011..0.012 rows=15 loops=1\) |
     301|                                                                                                   Buckets: 1024  Batches: 1  Memory Usage: 9kB |
     302|                                                                                                   ->  Seq Scan on has\_genre hg  \(cost=0.00..1.15 rows=15 width=8\) \(actual time=0.007..0.008 rows=15 loops=1\) |
     303|                                                                                       ->  Hash  \(cost=1.18..1.18 rows=18 width=8\) \(actual time=0.011..0.012 rows=18 loops=1\) |
     304|                                                                                             Buckets: 1024  Batches: 1  Memory Usage: 9kB |
     305|                                                                                             ->  Seq Scan on likes l  \(cost=0.00..1.18 rows=18 width=8\) \(actual time=0.006..0.008 rows=18 loops=1\) |
     306|                                                                                 ->  Hash  \(cost=1.13..1.13 rows=13 width=8\) \(actual time=0.009..0.009 rows=13 loops=1\) |
     307|                                                                                       Buckets: 1024  Batches: 1  Memory Usage: 9kB |
     308|                                                                                       ->  Seq Scan on reading\_list\_items rli  \(cost=0.00..1.13 rows=13 width=8\) \(actual time=0.005..0.006 rows=13 loops=1\) |
     309| Planning Time: 5.364 ms |
     310| Execution Time: 2.217 ms |
     311}}}
     312Average time: 2.78 ms
     313
     314The covering indexes were created and verified across all joined tables. The average execution time is 4.49 ms without indexes and 2.78 ms with indexes, based on 10 runs each. In the execution plan, idx_users_covering and writer_pkey are used as Index Only Scans. The remaining tables (story, chapter, comment, has_genre, likes, reading_list_items, collaboration) use Seq Scan or Hash Join because the dataset is small enough that sequential scans and in-memory hashing remain cheaper than index lookups at this data volume. The indexes are kept as they will be automatically utilized by the planner as data volume grows.
    316315
    317316== Scenario 2 — Quarterly writer performance report