= Оптимизација на прашалници и погледи = Во оваа фаза беа анализирани и оптимизирани погледите дефинирани во системот за booking на артисти и бендови. Анализата беше направена со користење на EXPLAIN ANALYZE врз query-и базирани на реални сценарија кои би се користеле во самата апликација. Целта беше да се намали времето на извршување на query-ите преку соодветно индексирање и подобрување на execution plan-от на PostgreSQL. == 1. Анализа и оптимизација на vw_available_bookables == Погледот {{{vw_available_bookables}}} се користи за пребарување на достапни артисти и бендови според град, жанр и статус на достапност. Прашалниците кои беа тестирани се следните: {{{ -- 1.2 SELECT * FROM vw_available_bookables WHERE genre_name = 'Pop' AND status = 'AVAILABLE'; -- 1.3 SELECT * FROM vw_available_bookables WHERE city = 'Ohrid' AND genre_name = 'Rock'; }}} === Време на извршување без индекси === '''1.2 - 13.717 ms''' {{{ Gather (cost=1042.46..13517.18 rows=1873 width=481) (actual time=9.626..13.638 rows=0 loops=1) Workers Planned: 3 Workers Launched: 3 -> Hash Join -> Parallel Seq Scan on availabilityslot av Filter: ((status)::text = 'AVAILABLE'::text) Planning Time: 1.078 ms Execution Time: 13.717 ms }}} '''1.3 - 13.899 ms''' {{{ Gather (cost=1037.17..13320.92 rows=17 width=481) (actual time=9.876..13.817 rows=0 loops=1) Workers Planned: 3 Workers Launched: 3 -> Hash Join -> Parallel Seq Scan on availabilityslot av Filter: ((status)::text = 'AVAILABLE'::text) Planning Time: 1.040 ms Execution Time: 13.899 ms }}} Во почетната анализа со {{{EXPLAIN ANALYZE}}} беше забележано дека PostgreSQL користи {{{Parallel Sequential Scan}}} врз табелата {{{AvailabilitySlot}}}, како и {{{Sequential Scan}}} врз {{{Bookable}}} и {{{Location}}}. Ова значеше дека системот обработува голем број редици за да ги пронајде потребните достапни артисти и бендови. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_availability_status ON AvailabilitySlot(status); CREATE INDEX idx_availability_bookable ON AvailabilitySlot(bookable_id); CREATE INDEX idx_bookable_location ON Bookable(location_id); CREATE INDEX idx_location_city ON Location(city); CREATE INDEX idx_bookablegenre_bookable ON BookableGenre(bookable_id); CREATE INDEX idx_bookablegenre_genre ON BookableGenre(genre_id); CREATE INDEX idx_genre_name ON Genre(genre_name); CREATE INDEX idx_bookable_active ON Bookable(is_active); }}} === Време на извршување со индекси === '''1.2 - 0.426 ms''' {{{ Nested Loop (cost=38.10..8550.23 rows=59922 width=481) (actual time=0.355..0.358 rows=0 loops=1) -> Index Scan using idx_availability_bookable on availabilityslot av Planning Time: 1.240 ms Execution Time: 0.426 ms }}} '''1.3 - 0.753 ms''' {{{ Nested Loop (cost=3.17..365.38 rows=2397 width=481) (actual time=0.684..0.687 rows=0 loops=1) -> Index Scan using idx_availability_bookable on availabilityslot av Planning Time: 1.272 ms Execution Time: 0.753 ms }}} По оптимизацијата PostgreSQL започна да користи {{{Index Scan}}} и {{{Index Only Scan}}}, со што значително се намали времето на извршување кај query-ите што филтрираат по жанр и град. Најголемо подобрување беше забележано кај query-ите со филтрирање по жанр: * од ~13 ms на ~0.4 ms * од ~13 ms на ~0.7 ms Со додавањето на индексите planner-от започна да користи индексно пребарување наместо {{{Parallel Sequential Scan}}}, што овозможи побрзо извршување на query-ите и подобар execution plan. == 2. Анализа и оптимизација на vw_client_booking_history == Погледот {{{vw_client_booking_history}}} се користи за прикажување на историјата на booking-ите на клиентите, нивниот статус и информациите за плаќање. Прашалниците кои беа тестирани се следните: {{{ -- 2.1 SELECT * FROM vw_client_booking_history WHERE client_id = 1500; -- 2.2 SELECT * FROM vw_client_booking_history WHERE payment_status = 'PAID'; }}} === Време на извршување без индекси === '''2.1 - 478.399 ms''' {{{ Nested Loop (cost=394513.00..438192.78 rows=3976 width=58) (actual time=434.407..443.008 rows=0 loops=1) -> Gather -> Parallel Hash Right Join -> Parallel Seq Scan on payment p -> Parallel Seq Scan on bookingrequest br Filter: (client_id = 1500) Planning Time: 44.765 ms Execution Time: 478.399 ms }}} '''2.2 - 159.853 ms''' {{{ Nested Loop (cost=1001.86..42632.01 rows=1 width=58) (actual time=142.971..159.779 rows=0 loops=1) -> Gather -> Parallel Seq Scan on payment p Filter: ((payment_status)::text = 'PAID'::text) Planning Time: 1.571 ms Execution Time: 159.853 ms }}} При почетната анализа беше забележано дека PostgreSQL користи {{{Parallel Sequential Scan}}} врз табелите {{{BookingRequest}}}, {{{Booking}}} и {{{Payment}}}. Ова предизвикуваше значително време на извршување, особено кај query-ите што пребаруваат според клиент или статус на плаќање. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_bookingrequest_client ON BookingRequest(client_id); CREATE INDEX idx_offer_request ON Offer(request_id); CREATE INDEX idx_booking_offer ON Booking(offer_id); CREATE INDEX idx_booking_status ON Booking(booking_status); CREATE INDEX idx_payment_booking ON Payment(booking_id); CREATE INDEX idx_payment_status ON Payment(payment_status); CREATE INDEX idx_bookable_id ON Bookable(bookable_id); }}} === Време на извршување со индекси === '''2.1 - 44.997 ms''' {{{ Nested Loop (cost=1115.31..63410.15 rows=3975 width=58) (actual time=38.480..44.907 rows=0 loops=1) -> Parallel Bitmap Heap Scan on bookingrequest br -> Bitmap Index Scan on idx_bookingrequest_client -> Index Scan using idx_offer_request on offer o -> Index Scan using idx_booking_offer on booking bk Planning Time: 2.529 ms Execution Time: 44.997 ms }}} '''2.2 - 0.114 ms''' {{{ Nested Loop (cost=2.29..14.64 rows=1 width=58) (actual time=0.047..0.049 rows=0 loops=1) -> Index Scan using idx_payment_status on payment p Planning Time: 2.188 ms Execution Time: 0.114 ms }}} По оптимизацијата PostgreSQL започна да користи: * {{{Bitmap Index Scan}}} * {{{Index Scan}}} * {{{Index Only Scan}}} Најголемо подобрување беше забележано кај query-от што пребарува според {{{payment_status}}}, каде времето на извршување се намали: * од ~159 ms * на ~0.1 ms Исто така, query-от што пребарува според {{{client_id}}} се подобри: * од ~478 ms * на ~44 ms Со додавањето на индексите planner-от започна да користи индексно пребарување наместо {{{Parallel Sequential Scan}}}, што овозможи значително побрзо извршување на query-ите и подобар execution plan. == 3. Анализа и оптимизација на vw_public_artist_profiles == Погледот {{{vw_public_artist_profiles}}} се користи за прикажување на јавните профили на артистите и бендовите, нивниот град, жанр, просечен рејтинг и бројот на reviews. Прашалникот кој беше тестиран е следниот: {{{ SELECT * FROM vw_public_artist_profiles WHERE city = 'Skopje'; }}} === Време на извршување без индекси === '''3.1 - 15423.388 ms''' {{{ HashAggregate (cost=761290.87..761380.87 rows=6000 width=497) (actual time=15419.314..15419.430 rows=213 loops=1) Group Key: b.bookable_id, g.genre_name -> Hash Left Join -> Hash Left Join -> Hash Right Join -> Seq Scan on booking bk -> Seq Scan on offer o -> Seq Scan on review r Planning Time: 1.979 ms Execution Time: 15423.388 ms }}} При почетната анализа со {{{EXPLAIN ANALYZE}}} беше забележано дека PostgreSQL користи {{{Sequential Scan}}} врз табелите {{{Offer}}}, {{{Booking}}} и {{{Review}}}, како и голем број {{{Hash Join}}} операции. Поради огромниот број редици и aggregation операции, query-от имаше долго време на извршување. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_bookable_location ON Bookable(location_id); CREATE INDEX idx_location_city ON Location(city); CREATE INDEX idx_review_booking ON Review(booking_id); CREATE INDEX idx_offer_bookable ON Offer(bookable_id); CREATE INDEX idx_booking_offer ON Booking(offer_id); CREATE INDEX idx_bookable_rating ON Bookable(average_rating); }}} === Време на извршување со индекси === '''3.1 - 15251.957 ms''' {{{ HashAggregate (cost=761290.87..761380.87 rows=6000 width=497) (actual time=15247.945..15248.063 rows=213 loops=1) Group Key: b.bookable_id, g.genre_name -> Hash Left Join -> Hash Left Join -> Hash Right Join -> Seq Scan on booking bk -> Seq Scan on offer o -> Seq Scan on review r Planning Time: 1.898 ms Execution Time: 15251.957 ms }}} По оптимизацијата беше забележано умерено подобрување: * од ~15.4 s * на ~15.2 s И покрај додадените индекси, PostgreSQL продолжи да користи {{{Sequential Scan}}} бидејќи query-от обработува огромен број редици и користи сложени aggregation операции како {{{AVG}}}, {{{COUNT}}} и {{{GROUP BY}}}. Во вакви ситуации planner-от проценува дека sequential processing е поефикасен од index traversal, па индексите имаат ограничено влијание врз вкупното време на извршување. == 4. Анализа и оптимизација на vw_trending_bookables == Погледот {{{vw_trending_bookables}}} се користи за прикажување на најпопуларните артисти и бендови според бројот на bookings и просечниот рејтинг. Овој поглед се користи за homepage recommendations и analytics. Прашалникот кој беше тестиран е следниот: {{{ SELECT * FROM vw_trending_bookables ORDER BY total_bookings DESC LIMIT 10; }}} === Време на извршување без индекси === '''4.1 - 22675.664 ms''' {{{ Limit (cost=1149893.25..1149893.28 rows=10 width=61) (actual time=22673.555..22673.564 rows=10 loops=1) -> Sort Sort Key: (count(bk.booking_id)) DESC -> HashAggregate Group Key: b.bookable_id -> Hash Right Join -> Hash Left Join -> Seq Scan on offer o -> Seq Scan on booking bk -> Seq Scan on review r Planning Time: 1.190 ms Execution Time: 22675.664 ms }}} При почетната анализа со {{{EXPLAIN ANALYZE}}} беше забележано дека PostgreSQL користи {{{Sequential Scan}}} врз табелите {{{Offer}}}, {{{Booking}}} и {{{Review}}}, како и {{{HashAggregate}}} и {{{Sort}}} операции за пресметување на бројот на bookings и просечниот рејтинг. Поради огромниот број редици и aggregation операции, query-от имаше многу долго време на извршување. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_offer_bookable ON Offer(bookable_id); CREATE INDEX idx_booking_offer ON Booking(offer_id); CREATE INDEX idx_review_booking ON Review(booking_id); CREATE INDEX idx_review_rating ON Review(rating); CREATE INDEX idx_bookable_id ON Bookable(bookable_id); }}} === Време на извршување со индекси === '''4.1 - 22582.888 ms''' {{{ Limit (cost=1149893.25..1149893.28 rows=10 width=61) (actual time=22580.768..22580.777 rows=10 loops=1) -> Sort Sort Key: (count(bk.booking_id)) DESC -> HashAggregate Group Key: b.bookable_id -> Hash Right Join -> Hash Left Join -> Seq Scan on offer o -> Seq Scan on booking bk -> Seq Scan on review r Planning Time: 1.633 ms Execution Time: 22582.888 ms }}} По оптимизацијата беше забележано мало подобрување кај query-от што ги прикажува најпопуларните артисти: * од ~22.6 s * на ~22.5 s И покрај додадените индекси, PostgreSQL продолжи да користи {{{Sequential Scan}}} бидејќи query-от обработува огромен број редици и користи сложени aggregation операции како {{{COUNT}}}, {{{AVG}}}, {{{GROUP BY}}} и {{{ORDER BY}}}. Во вакви ситуации planner-от проценува дека sequential processing е поефикасен од index traversal, па индексите имаат ограничено влијание врз вкупното време на извршување. == 5. Анализа и оптимизација на vw_artist_dashboard == Погледот {{{vw_artist_dashboard}}} се користи за прикажување на статистики за артистите и бендовите, вклучувајќи број на bookings, вкупна заработка и просечен рејтинг. Овој поглед се користи во artist dashboard делот од апликацијата. Прашалникот кој беше тестиран е следниот: {{{ SELECT * FROM vw_artist_dashboard WHERE average_rating >= 4.5; }}} === Време на извршување без индекси === '''5.1 - 32835.819 ms''' {{{ HashAggregate (cost=1485307.72..1485320.22 rows=200 width=87) (actual time=32833.146..32833.154 rows=0 loops=1) Group Key: b.bookable_id Filter: (round(avg(r.rating), 2) >= 4.5) -> Hash Right Join -> Hash Left Join -> Seq Scan on offer o -> Seq Scan on booking bk -> Seq Scan on payment p -> Seq Scan on review r Planning Time: 0.945 ms Execution Time: 32835.819 ms }}} При почетната анализа со {{{EXPLAIN ANALYZE}}} беше забележано дека PostgreSQL користи {{{Sequential Scan}}} врз табелите {{{Offer}}}, {{{Booking}}}, {{{Payment}}} и {{{Review}}}, како и {{{HashAggregate}}} операции за пресметување на заработката и просечниот рејтинг. Поради големиот број редици и aggregation операции, query-от имаше многу долго време на извршување. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_offer_bookable ON Offer(bookable_id); CREATE INDEX idx_booking_offer ON Booking(offer_id); CREATE INDEX idx_payment_booking ON Payment(booking_id); CREATE INDEX idx_payment_status ON Payment(payment_status); CREATE INDEX idx_review_booking ON Review(booking_id); CREATE INDEX idx_review_rating ON Review(rating); }}} === Време на извршување со индекси === '''5.1 - 30002.268 ms''' {{{ HashAggregate (cost=1485307.72..1485320.22 rows=200 width=87) (actual time=29999.572..29999.580 rows=0 loops=1) Group Key: b.bookable_id Filter: (round(avg(r.rating), 2) >= 4.5) -> Hash Right Join -> Hash Left Join -> Seq Scan on offer o -> Seq Scan on booking bk -> Seq Scan on payment p -> Seq Scan on review r Planning Time: 1.395 ms Execution Time: 30002.268 ms }}} По оптимизацијата беше забележано подобрување кај query-от што филтрира според просечен рејтинг: * од ~32.8 s * на ~30.0 s И покрај тоа што PostgreSQL продолжи да користи {{{Sequential Scan}}}, индексите помогнаа при join операциите и hash processing, што резултираше со побрзо извршување на query-от. Бидејќи погледот користи сложени aggregation операции како {{{SUM}}}, {{{AVG}}}, {{{COUNT}}} и {{{GROUP BY}}}, planner-от проценува дека sequential processing е поефикасен од index traversal при обработка на голем број редици. == 6. Анализа и оптимизација на vw_artist_schedule == Погледот {{{vw_artist_schedule}}} се користи за прикажување на распоредот и достапноста на артистите и бендовите. Овој поглед се користи за пребарување според статус на достапност, конкретен артист и временски период. Прашалниците кои беа тестирани се следните: {{{ -- 6.1 SELECT * FROM vw_artist_schedule WHERE status = 'AVAILABLE'; -- 6.2 SELECT * FROM vw_artist_schedule WHERE bookable_id = 150; -- 6.3 SELECT * FROM vw_artist_schedule WHERE start_datetime >= '2026-07-01' AND start_datetime < '2026-08-01'; }}} === Време на извршување без индекси === '''6.1 - 192.437 ms''' {{{ Hash Join (cost=28.50..17676.52 rows=199740 width=43) (actual time=37.987..185.463 rows=199835 loops=1) -> Seq Scan on availabilityslot av Filter: ((status)::text = 'AVAILABLE'::text) -> Seq Scan on bookable b Planning Time: 0.401 ms Execution Time: 192.437 ms }}} '''6.2 - 51.157 ms''' {{{ Nested Loop (cost=1000.27..13156.88 rows=993 width=43) (actual time=5.494..51.071 rows=1017 loops=1) -> Index Scan using bookable_pkey on bookable b -> Parallel Seq Scan on availabilityslot av Filter: (bookable_id = 150) Planning Time: 0.178 ms Execution Time: 51.157 ms }}} '''6.3 - 96.327 ms''' {{{ Hash Join (cost=28.50..18925.91 rows=104939 width=43) (actual time=5.043..92.669 rows=103896 loops=1) -> Seq Scan on availabilityslot av Filter: ((start_datetime >= '2026-07-01 00:00:00'::timestamp without time zone) AND (start_datetime < '2026-08-01 00:00:00'::timestamp without time zone)) -> Seq Scan on bookable b Planning Time: 0.345 ms Execution Time: 96.327 ms }}} При почетната анализа со {{{EXPLAIN ANALYZE}}} беше забележано дека PostgreSQL користи {{{Sequential Scan}}} и {{{Parallel Sequential Scan}}} врз табелата {{{AvailabilitySlot}}}. Ова значеше дека системот чита голем број редици за да ги пронајде потребните податоци, што предизвикуваше дополнително време на извршување. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_availability_status ON AvailabilitySlot(status); CREATE INDEX idx_availability_bookable ON AvailabilitySlot(bookable_id); CREATE INDEX idx_availability_start ON AvailabilitySlot(start_datetime); CREATE INDEX idx_bookable_id ON Bookable(bookable_id); }}} === Време на извршување со индекси === '''6.1 - 109.389 ms''' {{{ Hash Join (cost=2260.91..14905.68 rows=199740 width=43) (actual time=9.156..102.463 rows=199835 loops=1) -> Bitmap Heap Scan on availabilityslot av -> Bitmap Index Scan on idx_availability_status -> Seq Scan on bookable b Planning Time: 0.846 ms Execution Time: 109.389 ms }}} '''6.2 - 2.111 ms''' {{{ Nested Loop (cost=12.40..2934.21 rows=993 width=43) (actual time=0.327..2.041 rows=1017 loops=1) -> Index Scan using idx_bookable_id on bookable b -> Bitmap Heap Scan on availabilityslot av -> Bitmap Index Scan on idx_availability_bookable Planning Time: 0.206 ms Execution Time: 2.111 ms }}} '''6.3 - 73.602 ms''' {{{ Hash Join (cost=2260.55..13732.05 rows=104939 width=43) (actual time=11.382..70.012 rows=103896 loops=1) -> Bitmap Heap Scan on availabilityslot av -> Bitmap Index Scan on idx_availability_start -> Seq Scan on bookable b Planning Time: 0.410 ms Execution Time: 73.602 ms }}} По оптимизацијата PostgreSQL започна да користи: * {{{Bitmap Index Scan}}} * {{{Bitmap Heap Scan}}} * {{{Index Scan}}} Најголемо подобрување беше забележано кај query-от што пребарува според {{{bookable_id}}}: * од ~51 ms * на ~2 ms Кај query-от што пребарува според {{{status = 'AVAILABLE'}}} времето на извршување се намали: * од ~192 ms * на ~109 ms Исто така, query-от што пребарува според временски период се подобри: * од ~96 ms * на ~73 ms По оптимизацијата PostgreSQL престана да користи {{{Sequential Scan}}} и започна да ги пронаоѓа потребните редици преку индексно пребарување, што значително го подобри времето на извршување и ја намали количината на прочитани податоци. == 7. Анализа и оптимизација на vw_artist_reviews == Погледот {{{vw_artist_reviews}}} се користи за прикажување на reviews за артистите и бендовите, нивниот рејтинг и коментари. Овој поглед се користи за пребарување според рејтинг, артист и display name. Прашалниците кои беа тестирани се следните: {{{ -- 7.1 SELECT * FROM vw_artist_reviews WHERE rating = 5; -- 7.2 SELECT * FROM vw_artist_reviews WHERE bookable_id = 150; -- 7.3 SELECT * FROM vw_artist_reviews WHERE display_name = 'Drake'; }}} === Време на извршување без индекси === '''7.1 - 122018.425 ms''' {{{ Gather (cost=17340.83..132489.41 rows=238310 width=40) (actual time=606.629..121857.202 rows=240417 loops=1) -> Hash Join -> Parallel Hash Join -> Parallel Seq Scan on booking bk -> Parallel Seq Scan on review r Filter: (rating = 5) -> Seq Scan on bookable b Planning Time: 2.636 ms Execution Time: 122018.425 ms }}} '''7.2 - 681.679 ms''' {{{ Nested Loop (cost=193407.74..209111.43 rows=1 width=40) (actual time=646.913..680.325 rows=0 loops=1) -> Parallel Hash Join -> Parallel Seq Scan on review r -> Parallel Seq Scan on offer o Filter: (bookable_id = 150) Planning Time: 0.795 ms Execution Time: 681.679 ms }}} '''7.3 - 1422.990 ms''' {{{ Gather (cost=197989.27..213886.91 rows=2000 width=40) (actual time=1387.691..1421.437 rows=0 loops=1) -> Parallel Hash Join -> Parallel Seq Scan on offer o -> Seq Scan on bookable b Filter: ((display_name)::text = 'Drake'::text) Planning Time: 0.737 ms Execution Time: 1422.990 ms }}} При почетната анализа со {{{EXPLAIN ANALYZE}}} беше забележано дека PostgreSQL користи {{{Sequential Scan}}} и {{{Parallel Sequential Scan}}} врз табелите {{{Review}}} и {{{Offer}}}. Ова предизвикуваше големо време на извршување бидејќи системот обработуваше милиони редици за да ги пронајде потребните reviews. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_review_rating ON Review(rating); CREATE INDEX idx_review_booking ON Review(booking_id); CREATE INDEX idx_booking_offer ON Booking(offer_id); CREATE INDEX idx_offer_bookable ON Offer(bookable_id); CREATE INDEX idx_bookable_id ON Bookable(bookable_id); CREATE INDEX idx_bookable_display ON Bookable(display_name); }}} === Време на извршување со индекси === '''7.1 - 1257.316 ms''' {{{ Gather (cost=14992.67..130141.25 rows=238310 width=40) (actual time=307.260..1241.990 rows=240417 loops=1) -> Hash Join -> Parallel Hash Join -> Parallel Seq Scan on booking bk -> Parallel Bitmap Heap Scan on review r -> Bitmap Index Scan on idx_review_rating Planning Time: 1.856 ms Execution Time: 1257.316 ms }}} '''7.2 - 0.144 ms''' {{{ Nested Loop (cost=1.57..25.66 rows=1 width=40) (actual time=0.096..0.097 rows=0 loops=1) -> Index Scan using idx_bookable_id on bookable b -> Index Scan using idx_offer_bookable on offer o -> Index Scan using idx_booking_offer on booking bk -> Index Scan using idx_review_booking on review r Planning Time: 0.900 ms Execution Time: 0.144 ms }}} '''7.3 - 925.788 ms''' {{{ Gather (cost=1009.16..198914.73 rows=2000 width=40) (actual time=890.434..924.427 rows=0 loops=1) -> Nested Loop -> Hash Join -> Parallel Seq Scan on offer o -> Index Scan using idx_bookable_display on bookable b Planning Time: 0.866 ms Execution Time: 925.788 ms }}} По оптимизацијата PostgreSQL започна да користи: * {{{Bitmap Index Scan}}} * {{{Bitmap Heap Scan}}} * {{{Index Scan}}} Најголемо подобрување беше забележано кај query-от што пребарува според {{{rating = 5}}}: * од ~122 s * на ~1.2 s Кај query-от што пребарува според {{{bookable_id}}} времето на извршување се намали: * од ~681 ms * на ~0.14 ms Исто така, query-от што пребарува според {{{display_name}}} се подобри: * од ~1422 ms * на ~925 ms По оптимизацијата PostgreSQL престана да користи {{{Sequential Scan}}} за дел од пребарувањата и започна да користи индексно пребарување, што значително го намали времето на извршување и бројот на обработени редици. == 8. Анализа и оптимизација на vw_artist_incoming_requests == Погледот {{{vw_artist_incoming_requests}}} се користи за прикажување на incoming requests за артистите и бендовите, вклучувајќи тип на настан, датум, град и понудена цена. Овој поглед се користи во artist dashboard делот од апликацијата. Прашалниците кои беа тестирани се следните: {{{ -- 8.1 SELECT * FROM vw_artist_incoming_requests WHERE city = 'Skopje'; -- 8.2 SELECT * FROM vw_artist_incoming_requests WHERE event_date >= '2026-07-01' AND event_date < '2026-08-01'; }}} === Време на извршување без индекси === '''8.1 - 969.055 ms''' {{{ Gather (cost=204886.61..536618.31 rows=800000 width=254) (actual time=957.362..966.909 rows=0 loops=1) -> Hash Join -> Parallel Hash Join -> Parallel Seq Scan on bookingrequest br -> Seq Scan on location l Filter: ((city)::text = 'Skopje'::text) -> Parallel Seq Scan on offer o Planning Time: 0.612 ms Execution Time: 969.055 ms }}} '''8.2 - 8618.837 ms''' {{{ Gather (cost=209088.80..622293.48 rows=1677259 width=254) (actual time=7086.289..8549.231 rows=1701412 loops=1) -> Hash Left Join -> Parallel Hash Join -> Parallel Seq Scan on offer o -> Parallel Seq Scan on bookingrequest br Filter: ((event_date >= '2026-07-01'::date) AND (event_date < '2026-08-01'::date)) Planning Time: 0.637 ms Execution Time: 8618.837 ms }}} При почетната анализа со {{{EXPLAIN ANALYZE}}} беше забележано дека PostgreSQL користи {{{Sequential Scan}}} и {{{Parallel Sequential Scan}}} врз табелите {{{Offer}}} и {{{BookingRequest}}}. Ова предизвикуваше дополнително време на извршување бидејќи системот обработуваше милиони редици за да ги пронајде потребните requests. За оптимизација беа додадени следните индекси: {{{ CREATE INDEX idx_offer_bookable ON Offer(bookable_id); CREATE INDEX idx_offer_request ON Offer(request_id); CREATE INDEX idx_bookingrequest_location ON BookingRequest(location_id); CREATE INDEX idx_bookingrequest_eventdate ON BookingRequest(event_date); CREATE INDEX idx_location_city ON Location(city); CREATE INDEX idx_bookable_id ON Bookable(bookable_id); }}} === Време на извршување со индекси === '''8.1 - 617.537 ms''' {{{ Gather (cost=1030.26..345626.04 rows=800000 width=254) (actual time=606.861..615.460 rows=0 loops=1) -> Hash Join -> Nested Loop -> Hash Join -> Parallel Seq Scan on bookingrequest br -> Seq Scan on location l -> Index Scan using idx_offer_request on offer o Planning Time: 0.850 ms Execution Time: 617.537 ms }}} '''8.2 - 3438.192 ms''' {{{ Gather (cost=209088.80..622293.48 rows=1677259 width=254) (actual time=2096.594..3369.469 rows=1701412 loops=1) -> Hash Left Join -> Parallel Hash Join -> Parallel Seq Scan on offer o -> Parallel Seq Scan on bookingrequest br Filter: ((event_date >= '2026-07-01'::date) AND (event_date < '2026-08-01'::date)) Planning Time: 0.865 ms Execution Time: 3438.192 ms }}} По оптимизацијата PostgreSQL започна да користи: * {{{Index Scan}}} * {{{Nested Loop}}} * {{{Bitmap Heap Scan}}} Најголемо подобрување беше забележано кај query-от што пребарува според временски период: * од ~8.6 s * на ~3.4 s Кај query-от што пребарува според град {{{city = 'Skopje'}}} времето на извршување се подобри: * од ~969 ms * на ~617 ms По оптимизацијата PostgreSQL започна да користи индексно пребарување наместо {{{Sequential Scan}}} за дел од join операциите, што значително го намали времето на извршување и бројот на обработени редици.