| | 1 | = Оптимизација на Прашалници и Анализа на Перформанси (QueryOptimization) = |
| | 2 | |
| | 3 | Оваа страница го прикажува процесот на детекција на критичните точки (bottlenecks) во системот кои настанаа по популацијата на базата со над 40 милиони записи, како и успешната стратегија за оптимизација преку имплементација на соодветни индекси. |
| | 4 | |
| | 5 | --- |
| | 6 | |
| | 7 | == 1. Детекција на критични точки во извршувањето == |
| | 8 | |
| | 9 | При анализа на извршните планови на базата, утврдено е дека најголемо забавување се случува кај погледите и комплексните кверија кои вршат агрегација и филтрирање врз најобемните табели во системот: `Rating` (со преку 24 милиони записи), `WatchHistory` (10 милиони) и `Review` (10 милиони). |
| | 10 | |
| | 11 | Како примарен тест-случај за анализа беше земен погледот '''view_top_rated_content'''. Овој поглед е од исклучителна важност бидејќи ги прикажува најпопуларните и најдобро оценетите содржини на почетната страна на корисничкиот интерфејс — првото нешто што корисникот го гледа при вклучување на сервисот. |
| | 12 | |
| | 13 | === Иницијално мерење (Без индекси) === |
| | 14 | Пред оптимизацијата, извршувањето на погледот генерираше енормно забавување поради потребата од целосно скенирање на табелите (Sequential Scan). |
| | 15 | * '''Почетно извршно време:''' ~13.5 секунди (13500 ms). |
| | 16 | * '''Причина:''' Секоја агрегација (`AVG`, `COUNT`) или филтрирање преку надворешни клучеви во `JOIN` операциите предизвикуваше базата да ги чита сите милиони записи директно од дискот во меморија без никаков референтен патоказ. |
| | 17 | |
| | 18 | --- |
| | 19 | |
| | 20 | == 2. Имплементација на Индекси на Надворешни Клучеви (FK Indexes) == |
| | 21 | |
| | 22 | За да се овозможи брзо и ефикасно поврзување (JOIN) на трансакциските табели со матичните табели за корисници (`User`) и содржини (`Media`), имплементиравме стратегија на индексирање на сите критични надворешни клучеви (`FOREIGN KEY`). |
| | 23 | |
| | 24 | Со ова, наместо скапиот `Sequential Scan`, менаџерот на базата (PostgreSQL Query Planner) може да искористи `Index Scan` или `Bitmap Index Scan`. |
| | 25 | |
| | 26 | Ги извршивме следните оптимизациски наредби во базата: |
| | 27 | |
| | 28 | {{{ |
| | 29 | #!sql |
| | 30 | -- Оптимизација на табелата Rating (24 милиони записи) |
| | 31 | -- Овозможува моментално групирање и пресметка на просечен рејтинг по содржина |
| | 32 | CREATE INDEX idx_rating_content ON Rating (ContentContentID); |
| | 33 | CREATE INDEX idx_rating_user ON Rating (UserUserID); |
| | 34 | |
| | 35 | -- Оптимизација на табелата WatchHistory (10 милиони записи) |
| | 36 | -- Овозможува брз дофат на историјата на гледање за конкретен корисник/медиум |
| | 37 | CREATE INDEX idx_watchhistory_content ON WatchHistory (ContentContentID); |
| | 38 | CREATE INDEX idx_watchhistory_user ON WatchHistory (UserUserID); |
| | 39 | |
| | 40 | -- Оптимизација на табелата Review (10 милиони записи) |
| | 41 | -- Овозможува брзо вчитување на коментари под деталниот приказ на филмови/серии |
| | 42 | CREATE INDEX idx_review_content ON Review (ContentContentID); |
| | 43 | CREATE INDEX idx_review_user ON Review (UserUserID); |
| | 44 | }}} |
| | 45 | |
| | 46 | --- |
| | 47 | |
| | 48 | == 3. Анализа со EXPLAIN ANALYZE и Резултати == |
| | 49 | |
| | 50 | За евалуација на успешноста на индексите, беше искористена наредбата `EXPLAIN ANALYZE`, која не само што го предвидува планот, туку реално го извршува прашалникот и враќа точни статистики за потрошеното време во милисекунди и користениот алгоритам за пребарување. |
| | 51 | |
| | 52 | {{{ |
| | 53 | #!sql |
| | 54 | EXPLAIN ANALYZE |
| | 55 | SELECT * FROM view_top_rated_content |
| | 56 | WHERE content_type = 'Movie' AND title LIKE 'A%'; |
| | 57 | }}} |
| | 58 | |
| | 59 | === Приказот на извршниот план пред и по оптимизацијата ни ги откри следните клучни промени: === |
| | 60 | |
| | 61 | 1. '''Елиминација на Sequential Scan:''' На местото каде што претходно стоеше `Seq Scan on rating`, сега Query Planner-от резултира со `Index Scan using idx_rating_content`. |
| | 62 | 2. '''Побрзи JOIN операции:''' Наместо тешки алгоритми за спојување кои бараат многу меморија, базата сега користи оптиматизиран `Hash Join` или `Merge Join` потпрен на претходно сортираните индексни дрва (B-Tree). |
| | 63 | |
| | 64 | === Финален ефект врз перформансите: === |
| | 65 | * Извршното време на комплексните кверија кои претходно траеја со секунди (или во потешки случаи со часови при посложени аналитички прашалници) се намали на **неколку милисекунди**. |
| | 66 | * Обезбедена е висока скалабилност, што значи дека дури и ако бројот на записи во `WatchHistory` или `Rating` се удвои, времето на одговор ќе остане во рамките на прифатливи граници за непречено корисничко искуство (Real-time Streaming Experience). |
| | 67 | |
| | 68 | > '''Заклучок:''' Иако креираните индекси зафаќаат дополнителен простор на дискот (физичка меморија) и минимално го забавуваат процесот на запишување (`INSERT`), драстичното намалување на времето на одговор при читање (`SELECT`) ја оправдува нивната имплементација во сооднос 1:100 во корист на перформансите на апликацијата. |
| | 69 | |
| | 70 | Тука може да ја видите деталната анализа на PDF file-от: [attachment:VidiDBQueryOptimization.pdf VidiDBQueryOptimization.pdf] |