| | 111 | == Scenario 7: Top Performing Components Report == |
| | 112 | Users analyze which components are most popular in recent builds with high ratings. This report filters builds by date, joins multiple tables and aggregates ratings with a quality threshold. \\ |
| | 113 | Optimization: Without indexes, the query performs sequential scans on the build table to filter by created_at, then joins to rating_build. \\ |
| | 114 | A date index enables efficient range filtering, reducing the scan from 75000 builds to only those in the relevant time window. \\ |
| | 115 | {{{ |
| | 116 | CREATE INDEX IF NOT EXISTS idx_build_created_at |
| | 117 | ON build(created_at); |
| | 118 | |
| | 119 | CREATE INDEX IF NOT EXISTS idx_rating_build_build_value |
| | 120 | ON rating_build(build_id, value); |
| | 121 | }}} |
| | 122 | |
| | 123 | The date index on build(created_at) eliminates full table scans for time-windowed queries \\ |
| | 124 | |
| | 125 | == Scenario 8: User Reputation Leaderboard Report == |
| | 126 | This report calculates user reputation scores by aggregating approved builds, favorites received, and average ratings per user. \\ |
| | 127 | Optimization: The partial index on approved builds significantly reduces the working dataset. Combined with indexes on the JOIN keys, this reduces buffer reads and eliminates unnecessary data processing. \\ |
| | 128 | {{{ |
| | 129 | CREATE INDEX IF NOT EXISTS idx_build_approved_user |
| | 130 | ON build(is_approved, user_id) WHERE is_approved = TRUE; |
| | 131 | |
| | 132 | CREATE INDEX IF NOT EXISTS idx_favorite_build_build_id |
| | 133 | ON favorite_build(build_id); |
| | 134 | }}} |
| | 135 | |
| | 136 | The composite partial index (is_approved, user_id) WHERE is_approved = TRUE is highly selective and perfect for analytics that only considers approved content. \\ |
| | 137 | |
| | 138 | == Scenario 9: Budget Tier Popularity Report == |
| | 139 | This report segments builds into price tiers (Budget, Mid-Range, High-End, Enthusiast) and calculates engagement metrics within the last 6 months. It requires filtering by both approval status and creation date, then aggregates favorites and ratings for each tier. \\ |
| | 140 | Optimization: A composite index covering all three filter columns (is_approved, created_at, total_price) which enables index-only scans for the initial filter. The partial index with WHERE clause reduces index size by excluding unapproved builds entirely. \\ |
| | 141 | {{{ |
| | 142 | CREATE INDEX IF NOT EXISTS idx_build_approved_created_price |
| | 143 | ON build(is_approved, created_at, total_price) WHERE is_approved = TRUE; |
| | 144 | }}} |
| | 145 | |
| | 159 | Example test for scenario 7: |
| | 160 | {{{ |
| | 161 | EXPLAIN (ANALYZE, BUFFERS) |
| | 162 | SELECT * FROM get_report_top_components(); |
| | 163 | }}} |
| | 164 | |
| | 165 | Example test for scenario 8: |
| | 166 | {{{ |
| | 167 | EXPLAIN (ANALYZE, BUFFERS) |
| | 168 | SELECT * FROM get_report_user_reputation_leaderboard(); |
| | 169 | }}} |
| | 170 | |
| | 171 | Example test for scenario 9: |
| | 172 | {{{ |
| | 173 | EXPLAIN (ANALYZE, BUFFERS) |
| | 174 | SELECT * FROM get_report_budget_tier_popularity(); |
| | 175 | }}} |
| | 176 | |
| 136 | | Result: The partial index improved query performance by dropping the execution time from 0.351ms to 0.219ms. Partial indexes are more efficient for frequently filtered subsets of data, so that's why they are ideal for the admin queries that only target pending builds. |
| 137 | | |
| 138 | | |
| 139 | | |
| 140 | | |
| 141 | | |
| | 191 | Result: The partial index improved query performance by dropping the execution time from 0.351ms to 0.219ms. \\ |
| | 192 | Partial indexes are more efficient for frequently filtered subsets of data, so that's why they are ideal for the admin queries that only target pending builds. \\ |
| | 193 | |
| | 194 | === Scenario 7: Top Performing Components Report === |
| | 195 | |
| | 196 | Without indexes: |
| | 197 | Buffers: shared hit=7684 |
| | 198 | Planning Time: 0.021 ms |
| | 199 | Execution Time: 506.953 ms |
| | 200 | |
| | 201 | With indexes: |
| | 202 | Buffers: shared hit=6379 read=351 |
| | 203 | Planning Time: 0.022 ms |
| | 204 | Execution Time: 468.190 ms |
| | 205 | |
| | 206 | Result: The date index improved query performance, while not much, still a modest improvement reducing it from 506.953ms to 468.190ms. \\ |
| | 207 | |
| | 208 | === Scenario 8: User Reputation Leaderboard Report === |
| | 209 | |
| | 210 | Without indexes: |
| | 211 | Buffers: shared hit=142884 dirtied=1, temp read=495 written=849 |
| | 212 | Planning Time: 0.029 ms |
| | 213 | Execution Time: 553.368 ms |
| | 214 | |
| | 215 | With indexes: |
| | 216 | Buffers: shared hit=142892 read=1, temp read=231 written=584 |
| | 217 | Planning Time: 0.022 ms |
| | 218 | Execution Time: 345.192 ms |
| | 219 | |
| | 220 | Result: Here the improvement is much more noticeable than on Scenario 7, reducing the time from 553.368ms to 345.192ms. \\ |
| | 221 | |
| | 222 | === Scenario 9: Budget Tier Popularity Report === |
| | 223 | |
| | 224 | Without indexes: |
| | 225 | Buffers: shared hit=1366 read=30 |
| | 226 | Planning Time: 0.020 ms |
| | 227 | Execution Time: 131.234 ms |
| | 228 | |
| | 229 | With indexes: |
| | 230 | Buffers: shared hit=1396 |
| | 231 | Planning Time: 0.029 ms |
| | 232 | Execution Time: 125.615 ms |
| | 233 | |
| | 234 | Result: Modest improvement, but the index still helped out with unnecessary reads, reducing time from 131.234ms to 125.615ms. \\ |
| | 235 | |
| | 236 | |
| | 237 | |
| | 238 | |