| | 1 | = Оптимизација на прашалници и погледи = |
| | 2 | |
| | 3 | === 1. Анализа на поглед 1: Статистика на археолошки локалитети (Site_Statistics) === |
| | 4 | |
| | 5 | 1. **Примарен филтер:** Примарниот филтер за погледот `Site_Statistics` е според `site_id` на археолошкиот локалитет. |
| | 6 | 2. **Случај на употреба:** Овој поглед е наменет за административен и аналитички преглед на статистички информации за секој археолошки локалитет во базата. Неговата главна цел е да овозможи брз и едноставен пристап до клучни податоци за конкретен локалитет преку пребарување според `site_id`, без потреба од пишување комплексни SQL барања над повеќе табели. |
| | 7 | |
| | 8 | Тест прашалникот кој се извршува е следниот: |
| | 9 | |
| | 10 | {{{ |
| | 11 | EXPLAIN ANALYZE |
| | 12 | SELECT * |
| | 13 | FROM Site_Statistics |
| | 14 | WHERE site_id = 100; |
| | 15 | }}} |
| | 16 | |
| | 17 | Преку овој view, корисникот може да добие интегриран приказ кој ги содржи основните информации за локалитетот (`site_id`, `site_name`, `region`), како и агрегирани статистики за: |
| | 18 | |
| | 19 | * вкупен број на археолошки објекти (`total_objects`) |
| | 20 | * вкупен број на фрагменти (`total_fragments`) |
| | 21 | |
| | 22 | ==== А. Состојба ПРЕД индексирање ==== |
| | 23 | |
| | 24 | * **Време на извршување на прашалникот пред индексирање:** |
| | 25 | **0.215 ms** |
| | 26 | |
| | 27 | * **Најбавни операции (Bottleneck Analysis):** |
| | 28 | |
| | 29 | Во позадина, view-от користи `LEFT JOIN` со агрегирани подзапити (`COUNT ... GROUP BY`) над табелите `Objects` и `Fragments`, со што се овозможува приказ и на локалитети кои немаат регистрирани објекти или фрагменти. Функцијата `COALESCE` се користи за замена на `NULL` вредности со 0, со што резултатите стануваат поконзистентни и попогодни за анализа. |
| | 30 | |
| | 31 | Најзначајни операции се: |
| | 32 | * агрегација над табелата `Objects` |
| | 33 | * агрегација над табелата `Fragments` |
| | 34 | * групирање според `site_id` |
| | 35 | |
| | 36 | ==== Б. Воведување на индекси ==== |
| | 37 | |
| | 38 | За подобрување на перформансите при пребарување и агрегација по `site_id`, имплементирани се следните индекси: |
| | 39 | |
| | 40 | {{{ |
| | 41 | CREATE INDEX idx_objects_site_id ON Objects(site_id); |
| | 42 | CREATE INDEX idx_fragments_site_id ON Fragments(site_id); |
| | 43 | }}} |
| | 44 | |
| | 45 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 46 | |
| | 47 | Овие индекси значително го намалуваат времето потребно за извршување на пребарувања и статистички пресметки, особено поради големиот обем на податоци во табелите `Objects` и `Fragments`, бидејќи PostgreSQL може да користи `Index Scan` наместо `Sequential Scan`. |
| | 48 | |
| | 49 | Како резултат, `Site_Statistics` претставува оптимизиран аналитички поглед кој ја поедноставува обработката на податоци, ја подобрува читливоста, овозможува повторна употреба на логиката и обезбедува ефикасен мониторинг на археолошките локалитети. |
| | 50 | |
| | 51 | * **Заклучок за Write-Impact:** |
| | 52 | |
| | 53 | Времето изминато во извршување на операциите `INSERT` и `UPDATE` по индексирање останува во прифатливи граници. Иако индексите додаваат минимален трошок при запишување, добиеното забрзување кај `SELECT` прашалниците ја оправдува нивната употреба. |
| | 54 | |
| | 55 | |
| | 56 | === 2. Анализа на поглед 2: Инвентар на заштитени локалитети (Protected_Sites_Inventory) === |
| | 57 | |
| | 58 | 1. **Примарен филтер:** Примарниот филтер за погледот `Protected_Sites_Inventory` е според статусот на заштита на локалитетот, односно `protection_status_id`, како и преку условот `ps.name = 'Заштитен'`. |
| | 59 | 2. **Случај на употреба:** Овој поглед е наменет за административен, институционален и аналитички преглед на сите археолошки локалитети кои имаат статус „Заштитен“. Неговата основна цел е да овозможи брз пристап до информации за заштитените локалитети и нивниот археолошки инвентар, без потреба од сложени SQL пребарувања низ повеќе поврзани табели. |
| | 60 | |
| | 61 | Тест прашалникот кој се извршува е следниот: |
| | 62 | |
| | 63 | {{{ |
| | 64 | EXPLAIN ANALYZE |
| | 65 | SELECT * |
| | 66 | FROM Protected_Sites_Inventory; |
| | 67 | }}} |
| | 68 | |
| | 69 | Преку овој view, корисникот може да добие структуриран приказ за секој заштитен локалитет, кој ги содржи следните информации: |
| | 70 | |
| | 71 | * идентификатор на локалитет (`site_id`) |
| | 72 | * име на локалитет (`site_name`) |
| | 73 | * регион (`region`) |
| | 74 | * година на откривање (`discovery_year`) |
| | 75 | * вкупен број на објекти поврзани со локалитетот (`total_objects_count`) |
| | 76 | |
| | 77 | ==== А. Состојба ПРЕД индексирање ==== |
| | 78 | |
| | 79 | * **Случај на анализа:** |
| | 80 | |
| | 81 | Овој поглед е особено корисен за државни институции, музеи, истражувачи и организации задолжени за заштита на културното наследство, бидејќи овозможува систематски увид во археолошките ресурси на локалитетите со највисок степен на заштита. |
| | 82 | |
| | 83 | * **Најбавни операции (Bottleneck Analysis):** |
| | 84 | |
| | 85 | Во неговата имплементација се користи `JOIN` помеѓу табелите `Sites`, `Regions` и `Protection_Status`, при што клучниот филтер е: |
| | 86 | |
| | 87 | {{{ |
| | 88 | WHERE ps.name = 'Заштитен' |
| | 89 | }}} |
| | 90 | |
| | 91 | Со ова се обезбедува приказ исклучиво на локалитети со активен статус на заштита. |
| | 92 | |
| | 93 | Дополнително, преку `LEFT JOIN` со агрегирана подтабела над `Objects`, се пресметува бројот на објекти по локалитет: |
| | 94 | |
| | 95 | {{{ |
| | 96 | SELECT site_id, COUNT(*) AS total_objects_count |
| | 97 | FROM Objects |
| | 98 | GROUP BY site_id |
| | 99 | }}} |
| | 100 | |
| | 101 | Функцијата `COALESCE` гарантира дека локалитетите без регистрирани објекти ќе бидат прикажани со вредност 0, наместо `NULL`, што овозможува поконзистентна анализа. |
| | 102 | |
| | 103 | ==== Б. Воведување на индекси ==== |
| | 104 | |
| | 105 | За оптимизација на перформансите, особено при филтрирање и пребарување, се користат следните индекси: |
| | 106 | |
| | 107 | {{{ |
| | 108 | CREATE INDEX idx_sites_status ON Sites(protection_status_id); |
| | 109 | CREATE INDEX idx_objects_site_id ON Objects(site_id); |
| | 110 | }}} |
| | 111 | |
| | 112 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 113 | |
| | 114 | Индексот `idx_sites_status` овозможува побрзо филтрирање на заштитените локалитети според нивниот статус, додека `idx_objects_site_id` ја подобрува ефикасноста при пресметка на бројот на објекти за секој локалитет. |
| | 115 | |
| | 116 | Како резултат, `Protected_Sites_Inventory` претставува специјализиран и оптимизиран поглед кој ја олеснува анализата на заштитените археолошки локалитети, обезбедува подобра институционална контрола, поддржува донесување одлуки за конзервација и овозможува поефикасно управување со националното културно наследство. |
| | 117 | |
| | 118 | |
| | 119 | === 3. Анализа на поглед 3: Тековна локација на предмет (Object_Current_Location) === |
| | 120 | |
| | 121 | 1. **Примарен филтер:** Примарен филтер за погледот `Object_Current_Location` ќе биде според `object_id` на предметот, а исто така ќе се користи и според името на институцијата каде што се наоѓа. |
| | 122 | 2. **Случај на употреба:** За овој поглед ни се важни перформансите, бидејќи без него се губи време при утврдување на тековната локација на предметот. |
| | 123 | |
| | 124 | Тест прашалникот кој се извршува е следниот: |
| | 125 | |
| | 126 | {{{ |
| | 127 | EXPLAIN ANALYZE |
| | 128 | SELECT * |
| | 129 | FROM Object_Current_Location |
| | 130 | WHERE object_id = 1340; |
| | 131 | }}} |
| | 132 | |
| | 133 | ==== А. Состојба ПРЕД индексирање ==== |
| | 134 | |
| | 135 | * **Време на извршување на прашалникот пред оптимизација:** |
| | 136 | **0.073 ms** |
| | 137 | |
| | 138 | * **Најбавни операции (Bottleneck Analysis):** |
| | 139 | |
| | 140 | Иницијалното време за извршување на погледот е 0.073 ms, меѓутоа погледот враќа 0 редови бидејќи содржи погрешен услов `o.object_id = o.object_id` кој нема вистинска врска со табелата `Institutions`. |
| | 141 | |
| | 142 | Поради тоа погледот е логички неточен и пристапуваме кон целосна замена на имплементацијата и индексирање. |
| | 143 | |
| | 144 | Најскапата операција е `Seq Scan on institutions` со `ORDER BY random()` — скенира сите 200 институции само за да врати 1 случаен ред, без никаква вистинска `JOIN` врска. |
| | 145 | |
| | 146 | ==== Б. Воведување на индекси ==== |
| | 147 | |
| | 148 | По замена на VIEW-от со вистински `JOIN` преку `Object_Location_History` и поставување на индекси: |
| | 149 | |
| | 150 | {{{ |
| | 151 | CREATE INDEX idx_olh_object_id ON Object_Location_History(object_id); |
| | 152 | CREATE INDEX idx_olh_end_date ON Object_Location_History(end_date); |
| | 153 | }}} |
| | 154 | |
| | 155 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 156 | |
| | 157 | Времето на извршување се подобри и погледот почна да враќа точни резултати. |
| | 158 | |
| | 159 | По оптимизацијата планерот го користи `Index Scan using idx_olh_object_id` наместо `Seq Scan`, а `Institutions` се бара преку примарен клуч. |
| | 160 | |
| | 161 | * **Ново време на извршување на прашалникот:** |
| | 162 | **0.262 ms** |
| | 163 | |
| | 164 | Ова време е прифатливо за апликацијата. |
| | 165 | |
| | 166 | * **Заклучок:** |
| | 167 | |
| | 168 | `Object_Current_Location` овозможува точно и ефикасно следење на тековната институција во која се наоѓа конкретен археолошки предмет. Со користење на `Object_Location_History` и условот `end_date IS NULL`, погледот ја прикажува само активната локација на предметот. |
| | 169 | |
| | 170 | |
| | 171 | === 4. Анализа на поглед 4: Класификација на предмет според култура (Object_with_Culture) === |
| | 172 | |
| | 173 | 1. **Примарен филтер:** Примарен филтер за погледот `Object_with_Culture` ќе биде според `object_id` на предметот, а исто така ќе се користи и според името на културата и категоријата на која припаѓа предметот. |
| | 174 | 2. **Случај на употреба:** За овој поглед ни се важни перформансите, бидејќи без него се губи време при класификација на предметите според култура и категорија. |
| | 175 | |
| | 176 | Тест прашалникот кој се извршува е следниот: |
| | 177 | |
| | 178 | {{{ |
| | 179 | EXPLAIN ANALYZE |
| | 180 | SELECT * |
| | 181 | FROM Object_with_Culture |
| | 182 | WHERE object_id = 150; |
| | 183 | }}} |
| | 184 | |
| | 185 | ==== А. Состојба ПРЕД индексирање ==== |
| | 186 | |
| | 187 | * **Време на извршување на прашалникот пред индексирање:** |
| | 188 | **252.083 ms** |
| | 189 | |
| | 190 | * **Најбавни операции (Bottleneck Analysis):** |
| | 191 | |
| | 192 | Ова не е прифатливо време за апликацијата па затоа пристапуваме кон индексирање. |
| | 193 | |
| | 194 | Најскапите операции се два `Seq Scan` — еден врз табелата `Culture` со 270 редови и еден врз `Categories` со 280 редови, при што и двата користат `ORDER BY random()` и лажен услов `o.object_id = o.object_id` кој нема вистинска врска со овие табели. |
| | 195 | |
| | 196 | Поради тоа погледот враќа произволни и логички неточни резултати. |
| | 197 | |
| | 198 | ==== Б. Воведување на индекси ==== |
| | 199 | |
| | 200 | Поставен е следниот индекс: |
| | 201 | |
| | 202 | {{{ |
| | 203 | CREATE INDEX idx_oc_object_id ON Object_Classification(object_id); |
| | 204 | }}} |
| | 205 | |
| | 206 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 207 | |
| | 208 | По оптимизацијата планерот користи: |
| | 209 | |
| | 210 | * `Index Scan using idx_oc_object_id` на `Object_Classification` |
| | 211 | * `Index Scan using culture_pkey` на `Culture` |
| | 212 | * `Index Scan using categories_pkey` на `Categories` |
| | 213 | |
| | 214 | Наместо `Seq Scan + ORDER BY random()`, сега се користат индекси и вистински `JOIN` врски. |
| | 215 | |
| | 216 | * **Ново време на извршување на прашалникот:** |
| | 217 | **0.142 ms** |
| | 218 | |
| | 219 | Времето на извршување падна од **252.083 ms** на **0.142 ms** — подобрување од **~1775 пати**. |
| | 220 | |
| | 221 | * **Заклучок:** |
| | 222 | |
| | 223 | `Object_with_Culture` овозможува брза и точна класификација на археолошките предмети според нивната култура и категорија. Оптимизацијата преку индексот на `Object_Classification(object_id)` ја елиминира потребата од непотребни целосни скенирања и овозможува директен пристап до релевантните класификациски записи. |
| | 224 | |
| | 225 | |
| | 226 | === 5. Анализа на поглед 5: Предмети на изложби (Exhibition_Objects) === |
| | 227 | |
| | 228 | 1. **Примарен филтер:** Примарен филтер за погледот `Exhibition_Objects` ќе биде според `exhibition_id` на изложбата, со цел да се прикажат сите предмети и институции кои учествуваат на одредена изложба. |
| | 229 | 2. **Случај на употреба:** За овој поглед ни се важни перформансите, бидејќи без него се губи време при преглед на предметите по изложби. |
| | 230 | |
| | 231 | Тест прашалникот кој се извршува е следниот: |
| | 232 | |
| | 233 | {{{ |
| | 234 | EXPLAIN ANALYZE |
| | 235 | SELECT * |
| | 236 | FROM Exhibition_Objects |
| | 237 | WHERE exhibition_id = 204050; |
| | 238 | }}} |
| | 239 | |
| | 240 | ==== А. Состојба ПРЕД индексирање ==== |
| | 241 | |
| | 242 | * **Време на извршување на прашалникот пред индексирање:** |
| | 243 | **1485.615 ms** |
| | 244 | |
| | 245 | * **Најбавни операции (Bottleneck Analysis):** |
| | 246 | |
| | 247 | Ова не е прифатливо време за апликацијата па затоа пристапуваме кон индексирање. |
| | 248 | |
| | 249 | Најскапите операции се: |
| | 250 | |
| | 251 | * `Seq Scan on objects` кој скенира сите 2 милиони предмети |
| | 252 | * `Seq Scan on exhibitions` со 5000 редови |
| | 253 | * `Seq Scan on institutions` со 200 редови |
| | 254 | |
| | 255 | Дополнително, погледот користи `ORDER BY random()` и лажен услов `o.object_id = o.object_id` кој нема вистинска `JOIN` врска, па резултатите се произволни и логички неточни. |
| | 256 | |
| | 257 | ==== Б. Воведување на индекси ==== |
| | 258 | |
| | 259 | Поставен е следниот индекс: |
| | 260 | |
| | 261 | {{{ |
| | 262 | CREATE INDEX idx_oe_exhibition_id ON Object_Exhibition(exhibition_id); |
| | 263 | }}} |
| | 264 | |
| | 265 | По првичното индексирање е добиено: |
| | 266 | |
| | 267 | {{{ |
| | 268 | Execution Time: 27304.836 ms |
| | 269 | }}} |
| | 270 | |
| | 271 | Ова не е во ред. `Index Scan using objects_pkey` за 100 loops значи дека за секој од 100-те редови се бара посебен lookup во `Objects` табелата со 2 милиони записи. |
| | 272 | |
| | 273 | Поради тоа треба додатен индекс на `Object_Exhibition` за `object_id`: |
| | 274 | |
| | 275 | {{{ |
| | 276 | CREATE INDEX idx_oe_object_id ON Object_Exhibition(object_id); |
| | 277 | }}} |
| | 278 | |
| | 279 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 280 | |
| | 281 | По оптимизацијата планерот користи: |
| | 282 | |
| | 283 | * `Bitmap Index Scan using idx_oe_exhibition_id` |
| | 284 | * `Index Scan using exhibitions_pkey` |
| | 285 | * `Index Scan using institutions_pkey` |
| | 286 | * `Index Scan using objects_pkey` |
| | 287 | |
| | 288 | * **Ново време на извршување на прашалникот:** |
| | 289 | **36.343 ms** |
| | 290 | |
| | 291 | Времето на извршување падна од **27304.836 ms** на **36.343 ms** — подобрување од **~751 пати**. |
| | 292 | |
| | 293 | * **Заклучок:** |
| | 294 | |
| | 295 | `Exhibition_Objects` станува значително поефикасен за приказ на предмети по изложби. Индексите на `Object_Exhibition(exhibition_id)` и `Object_Exhibition(object_id)` овозможуваат брзо пронаоѓање на релациите помеѓу изложбите и предметите, што е критично за музејски и административни прегледи. |
| | 296 | |
| | 297 | |
| | 298 | === 6. Анализа на поглед 6: Детали за истражувачки пристап (Research_Access_Details) === |
| | 299 | |
| | 300 | 1. **Примарен филтер:** Примарен филтер за погледот `Research_Access_Details` ќе биде според `user_id` на истражувачот, со цел да се прикажат сите барања за пристап до предмети и нивниот статус за одреден корисник. |
| | 301 | 2. **Случај на употреба:** За овој поглед ни се важни перформансите, бидејќи без него се губи време при преглед на пристапите на истражувачите. |
| | 302 | |
| | 303 | Тест прашалникот кој се извршува е следниот: |
| | 304 | |
| | 305 | {{{ |
| | 306 | EXPLAIN ANALYZE |
| | 307 | SELECT * |
| | 308 | FROM Research_Access_Details |
| | 309 | WHERE user_id = 1000; |
| | 310 | }}} |
| | 311 | |
| | 312 | ==== А. Состојба ПРЕД индексирање ==== |
| | 313 | |
| | 314 | * **Иницијална состојба:** |
| | 315 | |
| | 316 | Иницијалното време за извршување на погледот не можеше да се измери бидејќи стариот VIEW користеше `OFFSET` со `COUNT(*)` врз табела со 2 милиони редови, што предизвикуваше извршување подолго од 2 минути. |
| | 317 | |
| | 318 | Поради тоа погледот беше целосно нефункционален и пристапивме кон замена на целата имплементација со вистински `JOIN` врз табелата `Researcher_Access`. |
| | 319 | |
| | 320 | * **Време по замена на VIEW-от, но пред целосна оптимизација:** |
| | 321 | **51867 ms = 51 секунди** |
| | 322 | |
| | 323 | Ова време е исто така неприфатливо. |
| | 324 | |
| | 325 | ==== Б. Воведување на индекси ==== |
| | 326 | |
| | 327 | Поставени се следните индекси: |
| | 328 | |
| | 329 | {{{ |
| | 330 | CREATE INDEX idx_ra_user_id ON Researcher_Access(user_id); |
| | 331 | CREATE INDEX idx_ra_object_id ON Researcher_Access(object_id); |
| | 332 | CREATE INDEX idx_ra_institution_id ON Researcher_Access(institution_id); |
| | 333 | |
| | 334 | ANALYZE Researcher_Access; |
| | 335 | }}} |
| | 336 | |
| | 337 | Потоа е додаден и соодветен составен индекс: |
| | 338 | |
| | 339 | {{{ |
| | 340 | CREATE INDEX idx_ra_user_object ON Researcher_Access(user_id, object_id); |
| | 341 | }}} |
| | 342 | |
| | 343 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 344 | |
| | 345 | * **Најдобро постигнато време по оптимизација:** |
| | 346 | **146.949 ms** |
| | 347 | |
| | 348 | Понатамошно подобрување само со индекси не е можно поради следните причини: |
| | 349 | |
| | 350 | * погледот враќа голем број на резултати, односно 221+ редови |
| | 351 | * за секој ред прави посебен `Nested Loop JOIN` со табелата `Objects`, која содржи 2 милиони записи |
| | 352 | |
| | 353 | Кај вакви аналитички прашалници кои враќаат многу редови и работат со многу голема табела, индексите ретко кога можат значително да ги подобрат перформансите над одредена граница. |
| | 354 | |
| | 355 | * **Заклучок:** |
| | 356 | |
| | 357 | `Research_Access_Details` е важен административен поглед за следење на барањата за пристап од страна на истражувачите. Иако оптимизацијата значително ја подобрува состојбата во однос на нефункционалниот стар view, природата на прашалникот и големиот број записи значат дека времето останува повисоко во споредба со другите погледи. |
| | 358 | |
| | 359 | |
| | 360 | === 7. Анализа на поглед 7: Историја на третмани (Treatment_History) === |
| | 361 | |
| | 362 | 1. **Примарен филтер:** Примарен филтер за погледот `Treatment_History` ќе биде според `object_id` на предметот, со цел да се прикажат сите чекори на конзервација и третман извршени врз одреден предмет. |
| | 363 | 2. **Случај на употреба:** За овој поглед ни се важни перформансите, бидејќи без него се губи време при преглед на историјата на третмани. |
| | 364 | |
| | 365 | Тест прашалникот кој се извршува е следниот: |
| | 366 | |
| | 367 | {{{ |
| | 368 | EXPLAIN ANALYZE |
| | 369 | SELECT * |
| | 370 | FROM Treatment_History |
| | 371 | WHERE object_id = 100; |
| | 372 | }}} |
| | 373 | |
| | 374 | ==== А. Состојба ПРЕД индексирање ==== |
| | 375 | |
| | 376 | * **Иницијална состојба:** |
| | 377 | |
| | 378 | Иницијалното време за извршување на погледот не можеше да се измери бидејќи беше имплементиран како `MATERIALIZED VIEW` кој не дозволува филтрирање по `object_id`. |
| | 379 | |
| | 380 | Поради тоа пристапивме кон замена со обичен `VIEW`. |
| | 381 | |
| | 382 | ==== Б. Воведување на индекси ==== |
| | 383 | |
| | 384 | Постоечките индекси поставени претходно во кодот беа доволни за оптимално извршување на погледот: |
| | 385 | |
| | 386 | {{{ |
| | 387 | CREATE INDEX idx_tsl_treatment ON Treatment_Step_Log(treatment_id); |
| | 388 | CREATE INDEX idx_treatments_object ON Treatments(object_id); |
| | 389 | CREATE INDEX idx_tsl_treatment_user_step ON Treatment_Step_Log(treatment_id, performed_by_user, step_number); |
| | 390 | }}} |
| | 391 | |
| | 392 | Не се потребни дополнителни индекси. |
| | 393 | |
| | 394 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 395 | |
| | 396 | По замената времето на извршување изнесува: |
| | 397 | |
| | 398 | * **Ново време на извршување на прашалникот:** |
| | 399 | **0.549 ms** |
| | 400 | |
| | 401 | Ова е прифатливо време. |
| | 402 | |
| | 403 | Планерот веќе ги користи постоечките индекси: |
| | 404 | |
| | 405 | * `idx_treatments_object` на `Treatments(object_id)` |
| | 406 | * `idx_tsl_treatment` на `Treatment_Step_Log(treatment_id)` |
| | 407 | * `Index Scan using objects_pkey` |
| | 408 | * `Index Scan using users_pkey` |
| | 409 | |
| | 410 | * **Заклучок:** |
| | 411 | |
| | 412 | `Treatment_History` е оптимизиран поглед кој овозможува брз преглед на сите третмани и чекори на конзервација за конкретен археолошки предмет. Бидејќи постоечките индекси веќе ги покриваат главните `JOIN` и филтер услови, не е потребна дополнителна оптимизација. |
| | 413 | |
| | 414 | |
| | 415 | === 8. Анализа на поглед 8: Публикации со автори (Publications_with_Authors) === |
| | 416 | |
| | 417 | 1. **Примарен филтер:** Примарен филтер за погледот `Publications_with_Authors` ќе биде според `publication_id`, со цел да се прикажат сите автори на одредена публикација. |
| | 418 | 2. **Случај на употреба:** За овој поглед ни се важни перформансите, бидејќи без него се губи време при библиографски преглед на публикациите. |
| | 419 | |
| | 420 | Тест прашалникот кој се извршува е следниот: |
| | 421 | |
| | 422 | {{{ |
| | 423 | EXPLAIN ANALYZE |
| | 424 | SELECT * |
| | 425 | FROM Publications_with_Authors |
| | 426 | WHERE publication_id = 100; |
| | 427 | }}} |
| | 428 | |
| | 429 | ==== А. Состојба ПРЕД индексирање ==== |
| | 430 | |
| | 431 | * **Време на извршување на прашалникот пред индексирање:** |
| | 432 | **1158.266 ms** |
| | 433 | |
| | 434 | Ова време е неприфатливо. |
| | 435 | |
| | 436 | Погледот беше имплементиран како `MATERIALIZED VIEW` без можност за филтрирање, па пристапивме кон замена со обичен `VIEW`. |
| | 437 | |
| | 438 | ==== Б. Воведување на индекси ==== |
| | 439 | |
| | 440 | Поставени се следните индекси: |
| | 441 | |
| | 442 | {{{ |
| | 443 | CREATE INDEX idx_pa_publication_id ON Publication_Authors(publication_id); |
| | 444 | CREATE INDEX idx_pa_author_id ON Publication_Authors(author_id); |
| | 445 | |
| | 446 | ANALYZE Publication_Authors; |
| | 447 | ANALYZE Publications; |
| | 448 | }}} |
| | 449 | |
| | 450 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 451 | |
| | 452 | По оптимизацијата планерот користи: |
| | 453 | |
| | 454 | * `Index Only Scan using publication_authors_pkey` |
| | 455 | * `Index Scan using publications_pkey` |
| | 456 | * `Index Scan using authors_pkey` |
| | 457 | |
| | 458 | * **Ново време на извршување на прашалникот:** |
| | 459 | **24.479 ms** |
| | 460 | |
| | 461 | Времето на извршување падна од **1158.266 ms** на **24.479 ms** — подобрување од **~47 пати**. |
| | 462 | |
| | 463 | * **Заклучок:** |
| | 464 | |
| | 465 | `Publications_with_Authors` овозможува ефикасен библиографски преглед на публикациите и нивните автори. Оптимизацијата е особено важна бидејќи табелата `Publication_Authors` претставува M:N релација помеѓу публикации и автори, а индексите овозможуваат брзо филтрирање според конкретна публикација. |
| | 466 | |
| | 467 | |
| | 468 | === 9. Анализа на поглед 9: Целосен преглед на наследство (Heritage_Full_Overview) === |
| | 469 | |
| | 470 | 1. **Примарен филтер:** Примарен филтер за погледот `Heritage_Full_Overview` ќе биде според `site_id` на локалитетот, со цел да се прикажат сите фрагменти, предмети, региони и статус на заштита поврзани со одреден археолошки локалитет. |
| | 471 | 2. **Случај на употреба:** За овој поглед ни се важни перформансите, бидејќи работи врз табелата `Fragments` која содржи 10 милиони редови и прави `JOIN` со табелата `Objects` која содржи 2 милиони редови. |
| | 472 | |
| | 473 | Погледот беше претходно имплементиран како `MATERIALIZED VIEW` без можност за филтрирање по `site_id`. Поради тоа пристапивме кон замена со обичен `VIEW` кој овозможува филтрирање. |
| | 474 | |
| | 475 | Тест прашалникот кој се извршува е следниот: |
| | 476 | |
| | 477 | {{{ |
| | 478 | EXPLAIN ANALYZE |
| | 479 | SELECT * |
| | 480 | FROM Heritage_Full_Overview |
| | 481 | WHERE site_id = 100 |
| | 482 | LIMIT 10; |
| | 483 | }}} |
| | 484 | |
| | 485 | ==== А. Состојба ПРЕД индексирање ==== |
| | 486 | |
| | 487 | При мерење на иницијалното време на извршување, поради екстремно големата табела `Fragments` со 10 милиони редови, беше додаден `LIMIT 10` за да се добие мерливо време без да се чека неколку минути. |
| | 488 | |
| | 489 | * **Време на извршување на прашалникот пред индексирање:** |
| | 490 | **4055.439 ms = ~4 секунди** |
| | 491 | |
| | 492 | Ова е неприфатливо. |
| | 493 | |
| | 494 | * **Најбавни операции (Bottleneck Analysis):** |
| | 495 | |
| | 496 | Главниот проблем беше `Seq Scan on fragments`, кој скенираше сите 10 милиони редови со `Rows Removed by Filter: 47805`, односно го отфрлаше речиси целиот резултат. |
| | 497 | |
| | 498 | ==== Б. Воведување на индекси ==== |
| | 499 | |
| | 500 | Поставени се следните индекси: |
| | 501 | |
| | 502 | {{{ |
| | 503 | CREATE INDEX IF NOT EXISTS idx_fragments_site_id ON Fragments(site_id); |
| | 504 | CREATE INDEX IF NOT EXISTS idx_objects_site_id ON Objects(site_id); |
| | 505 | }}} |
| | 506 | |
| | 507 | ==== В. Состојба ПОСЛЕ индексирање ==== |
| | 508 | |
| | 509 | По поставувањето на индексите, планерот повеќе не прави `Seq Scan on fragments`, туку користи: |
| | 510 | |
| | 511 | * `Index Scan using idx_fragments_site_id on fragments` — наместо скенирање на 10 милиони редови |
| | 512 | * `Index Scan using objects_pkey on objects` |
| | 513 | * `Index Scan using sites_pkey on sites` |
| | 514 | * `Index Scan using regions_pkey on regions` |
| | 515 | * `Index Scan using protection_status_pkey on protection_status` |
| | 516 | |
| | 517 | * **Ново време на извршување на прашалникот:** |
| | 518 | **1.264 ms** |
| | 519 | |
| | 520 | Времето на извршување падна од **4055.439 ms** на **1.264 ms** — подобрување од **~3208 пати**. |
| | 521 | |
| | 522 | * **Заклучок:** |
| | 523 | |
| | 524 | `Heritage_Full_Overview` претставува еден од најважните аналитички погледи во системот, бидејќи овозможува централен преглед на фрагменти, предмети, региони и статус на заштита за конкретен локалитет. Индексирањето на `Fragments(site_id)` е клучно, бидејќи табелата `Fragments` содржи огромен број записи и без индекс прашалникот мора да скенира милиони редови. |