Changes between Initial Version and Version 1 of AdvancedTopics


Ignore:
Timestamp:
06/14/26 21:38:20 (7 days ago)
Author:
231066
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedTopics

    v1 v1  
     1= Напредни бази на податоци =
     2= Фаза 5 — Напредна тема: OLAP Податочни Коцки =
     3== Проект: Платформа за евиденција на избори ==
     4
     5Вовед
     6Online Analytical Processing (OLAP) е категорија на технологија за бази на податоци која овозможува брза, повеќедимензионална анализа на големи количини на податоци. За разлика од традиционалните OLTP (Online Transaction Processing) системи кои се оптимизирани за вметнување и ажурирање на поединечни записи, OLAP системите се дизајнирани за комплексни аналитички прашалници кои агрегираат податоци преку повеќе димензии истовремено.
     7
     8Во контекст на овој систем за евиденција на избори, примарните податоци се инхерентно аналитички — број на гласови, стапки на излезност, доделување мандати и перформанси на кандидати се мерки кои треба да се анализираат преку повеќе димензии: време, географија, политички ентитет и тип на избори.
     9
     10Извршувањето на овие аналитички прашалници директно врз сировите табели (vote_result: 1,4М записи, ballot: 19М записи, voter_election: 18М записи) би резулторило со неприфатливо долго време за одговор, особено кога се агрегира преку повеќе димензии.
     11
     12= Зошто OLAP податочни коцки? =
     13
     14Во нашата постоечка шема имаме следни аналитички табели:
     15
     16|| Табела || Записи || Употреба ||
     17|| vote_result || 1.4M || Агрегирани резултати по станица ||
     18|| ballot || 19M || Поединечни гласачки ливчиња ||
     19|| voter_election || 18M || Евиденција за излезност ||
     20|| candidate_party || 2.4K || Номинации на кандидати ||
     21|| candidate_list_item || 1M || Позиции на кандидатски листи ||
     22
     23Без OLAP, прашалник „Колкав е уделот на гласови на ВМРО-ДПМНЕ по региони во изборите 2024?" би барал:
     24
     25Спојување на vote_result (1,4М) со polling_station
     26
     27Спојување со region (563 записи) и political_entity
     28
     29Групирање и агрегирање на живо при секое барање
     30
     31Со OLAP податочните коцки, истиот прашалник чита неколку стотини однапред пресметани записи — моментално.
     32
     33= Техничка имплементација =
     34
     35==== Материјализирани погледи (Materialized Views)
     36Материјализираниот поглед во PostgreSQL е објект на база на податоци кој ги складира резултатите од прашалникот физички на диск, за разлика од регуларниот поглед кој го повторно извршува прашалникот при секој пристап.
     37
     38Синтакса:
     39{{{
     40CREATE MATERIALIZED VIEW mv_name AS
     41SELECT ... WITH DATA;
     42}}}
     43
     44Освежување на коцките:
     45{{{
     46REFRESH MATERIALIZED VIEW CONCURRENTLY mv_name;
     47}}}
     48
     49==== Операторот ROLLUP
     50ROLLUP е проширување на GROUP BY кое автоматски генерира подзбирни записи за хиерархиски групирања. За димензии (A, B, C), ROLLUP произведува:
     51
     52{{{
     53GROUP BY (A, B, C)  — најфин зрнест запис
     54GROUP BY (A, B)     — подзбир без C
     55GROUP BY (A)        — подзбир без B и C
     56GROUP BY ()         — вкупен збир
     57}}}
     58
     59NULL вредностите во излезот означуваат групирани (rolled-up) димензии. На пример, NULL во колоната region_name значит дека записот претставува агрегација преку сите региони.
     60
     61Функцијата GROUPING() враќа цел број кој означува кои димензии се групирани во секој запис:
     62
     63GROUPING(...) = 0 — најфин зрнест запис
     64
     65GROUPING(...) > 0 — некои димензии се групирани
     66
     67==== Просторни индекси (GIST)
     68Секоја материјализирана коцка е индексирана на најчесто филтрираните колони. Уникатен индекс е потребен на секоја коцка за поддршка на CONCURRENT освежување.
     69
     70= Податочни коцки =
     71
     72=== 1. mv_election_results_cube ===
     73
     74==== Опис:
     75Примарна аналитичка коцка на системот. Обезбедува комплетен повеќедимензионален поглед на резултатите од гласањето преку секоја комбинација на избори, географија и политички ентитет.
     76
     77==== Зошто е потребна:
     78Сировата табела vote_result содржи 1,4М записи. Секој прашалник кој прашува „Кој ентитет победи во одредена општина?" бара спојување на vote_result со polling_station, region, election и political_entity со агрегирање. Без коцката, ова скенира 1,4М записи при секое извршување. Со коцката, истиот прашалник чита неколку стотини однапред пресметани записи моментално.
     79
     80==== Димензии и Хиерархија:
     81|| Димензија || Хиерархија ||
     82|| Време || election_date → election_year ||
     83|| Географија || земја → плански регион → општина ||
     84|| Ентитет || entity_type → entity_name ||
     85|| Избори || election_type → election_name ||
     86
     87==== Мерки:
     88|| Мерка || Опис ||
     89|| total_votes || Сума на гласови за ентитетот ||
     90|| vote_share_pct || Процент на вкупните гласови ||
     91|| stations_reporting || Број на станици кои известуваат ||
     92
     93==== Нивоа генерирани со ROLLUP:
     94
     95Ниво 0 (најфино): гласови по ентитет по општина по избори
     96
     97Ниво 1: гласови по ентитет по плански регион по избори
     98
     99Ниво 2: гласови по ентитет по земја по избори
     100
     101Ниво 3: гласови по ентитет низ сите избори
     102
     103Ниво 4 (вкупно): вкупни гласови низ сите димензии
     104
     105==== Создадени индекси:
     106{{{
     107CREATE INDEX idx_cube1_election ON mv_election_results_cube(election_id);
     108CREATE INDEX idx_cube1_entity   ON mv_election_results_cube(entity_id);
     109CREATE INDEX idx_cube1_country  ON mv_election_results_cube(country_id);
     110CREATE INDEX idx_cube1_region   ON mv_election_results_cube(planning_region_id);
     111CREATE INDEX idx_cube1_grouping ON mv_election_results_cube(grouping_level);
     112CREATE INDEX idx_cube1_year     ON mv_election_results_cube(election_year);
     113CREATE INDEX idx_cube1_type     ON mv_election_results_cube(election_type);
     114CREATE UNIQUE INDEX idx_cube1_unique ON mv_election_results_cube(election_id, entity_id, country_id, planning_region_id, grouping_level);
     115}}}
     116
     117==== Примери на поддржани прашалници:
     118
     119„Кој ентитет освои највеќе гласови по регион на парламентарните избори 2024?"
     120
     121„Како се менуваат резултатите на СДСМ низ сите избори?"
     122
     123„Споредба на вкупните гласови МК vs Србија"
     124
     125=== 2. mv_turnout_cube ===
     126
     127==== Опис:
     128Ги анализира стапките на учество на гласачите преку географија и времето. Ја поддржува апликацијата со информации за тоа колку регистрирани гласачи навистина гласале на секои избори.
     129
     130==== Зошто е потребна:
     131Пресметувањето на излезноста бара комбинирање на три одделни големи табели: voter (10М записи) за регистрирани гласачи, voter_election (18М записи) за фактичко учество, и ballot (19М записи) за неважечки ливчиња. Спојувањето на овие три табели при секое барање е непрактично. Коцката ги однапред пресметува сите метрики за излезност на секое географско ниво.
     132
     133==== Димензии и Хиерархија:
     134|| Димензија || Хиерархија ||
     135|| Време || election_date → election_year ||
     136|| Географија || земја → плански регион → општина ||
     137|| Избори || election_type → election_name ||
     138
     139==== Мерки:
     140|| Мерка || Опис ||
     141|| registered_voters || Регистрирани гласачи во подрачјето ||
     142|| voters_checked_in || Гласачи кои навистина гласале ||
     143|| invalid_ballots || Неважечки ливчиња ||
     144|| turnout_pct || checked_in / registered × 100 ||
     145|| invalid_pct || invalid / checked_in × 100 ||
     146
     147==== Нивоа генерирани со ROLLUP:
     148
     149Ниво 0 (најфино): излезност по општина по избори
     150
     151Ниво 1: излезност по плански регион
     152
     153Ниво 2: излезност по земја по избори
     154
     155Ниво 3: излезност по избори
     156
     157Ниво 4 (вкупно): вкупна излезност низ се
     158
     159==== Создадени индекси:
     160{{{
     161CREATE INDEX idx_cube2_election ON mv_turnout_cube(election_id);
     162CREATE INDEX idx_cube2_country  ON mv_turnout_cube(country_id);
     163CREATE INDEX idx_cube2_region   ON mv_turnout_cube(planning_region_id);
     164CREATE INDEX idx_cube2_grouping ON mv_turnout_cube(grouping_level);
     165CREATE INDEX idx_cube2_year     ON mv_turnout_cube(election_year);
     166CREATE INDEX idx_cube2_type     ON mv_turnout_cube(election_type);
     167CREATE UNIQUE INDEX idx_cube2_unique ON mv_turnout_cube(election_id, country_id, planning_region_id, grouping_level);
     168}}}
     169
     170==== Примери на поддржани прашалници:
     171
     172„Која општина имаше највисока излезност на парламентарните избори 2020?"
     173
     174„Како се менува излезноста низ времето во Македонија наспрема Србија?"
     175
     176„Кој тип на избори историски има најниска стапка на неважечки ливчиња?"
     177
     178=== 3. mv_candidate_cube ===
     179
     180==== Опис:
     181Обезбедува преглед на кариерата на поединечни кандидати низ сите избори. Следи на колку избори учествувал секој кандидат, кои партии ги претставувал и на кои позиции бил на кандидатски листи.
     182
     183==== Зошто е потребна:
     184Анализата на кандидатите бара спојување на candidate (500К записи) со person (12М записи), candidate_party, candidate_list_item (1М записи) и election. Пресметувањето на статистики за кариера на живо при секое барање скенира милиони записи. Коцката ги однапред пресметува овие метрики на ниво на кандидат, партија и избори.
     185
     186==== Димензии и Хиерархија:
     187|| Димензија || Хиерархија ||
     188|| Кандидат || candidate_id → name → gender ||
     189|| Партија || party_id → party_name ||
     190|| Избори || election_type → election_year ||
     191
     192==== Мерки:
     193|| Мерка || Опис ||
     194|| elections_contested || Број на различни избори ||
     195|| parties_represented || Број на различни партии ||
     196|| best_list_position || Најдобра позиција на листа ||
     197|| worst_list_position || Најлоша позиција на листа ||
     198|| avg_list_position || Просечна позиција на листа ||
     199
     200==== Нивоа генерирани со ROLLUP:
     201
     202Ниво 0 (најфино): статистики по кандидат по партија по избори
     203
     204Ниво 1: по кандидат по партија (сите избори)
     205
     206Ниво 2: по кандидат (сите партии, сите избори) — преглед на кариера
     207
     208Ниво 3 (вкупно): агрегат низ сите кандидати
     209
     210==== Создадени индекси:
     211{{{
     212CREATE INDEX idx_cube3_candidate ON mv_candidate_cube(candidate_id);
     213CREATE INDEX idx_cube3_party     ON mv_candidate_cube(party_id);
     214CREATE INDEX idx_cube3_election  ON mv_candidate_cube(election_id);
     215CREATE INDEX idx_cube3_grouping  ON mv_candidate_cube(grouping_level);
     216CREATE INDEX idx_cube3_year      ON mv_candidate_cube(election_year);
     217CREATE UNIQUE INDEX idx_cube3_unique ON mv_candidate_cube(candidate_id, party_id, election_id, grouping_level);
     218}}}
     219
     220==== Примери на поддржани прашалници:
     221
     222„Кои кандидати учествувале на најмногу избори?"
     223
     224„Која партија историски номинирала најмногу кандидати?"
     225
     226„Каква е родовата застапеност на кандидатите по тип на избори?"
     227
     228=== 4. mv_party_dominance_cube ===
     229
     230==== Опис:
     231Ја анализира силата и конкурентниот рангинг на поединечни партии (не коалиции) низ сите избори и земји. Директно ги споредува перформансите на партиите независно дали настапувале самостојно или во коалиција.
     232
     233==== Зошто е потребна:
     234Табелата vote_result ги складира гласовите на ниво на ентитет — гласовите за коалиции се припишуваат на коалицискиот ентитет, не на поединечните партии. Анализата на перформансите на конкретна партија низ сите избори бара филтрирање, спојување и агрегирање со пресметување на ранг преку прозорски функции (window functions). Коцката ги однапред пресметува рангинзите и уделите на гласови на ниво на партија.
     235
     236==== Димензии и Хиерархија:
     237|| Димензија || Хиерархија ||
     238|| Партија || party_id → party_name → ideology ||
     239|| Избори || election_type → election_year ||
     240|| Географија || country_id → country_name ||
     241
     242==== Мерки:
     243|| Мерка || Опис ||
     244|| total_votes || Гласови добиени од партијата ||
     245|| vote_share_pct || Процент на вкупните гласови ||
     246|| rank_in_election || Конкурентски ранг (1 = најмногу) ||
     247
     248==== Нивоа генерирани со ROLLUP:
     249
     250Ниво 0 (најфино): гласови по партија по избори по земја
     251
     252Ниво 1: гласови по партија низ сите избори по земја
     253
     254Ниво 2: гласови по партија низ сите земји (вкупна кариера)
     255
     256Ниво 3 (вкупно): сите партии, сите избори
     257
     258==== Создадени индекси:
     259{{{
     260CREATE INDEX idx_cube4_party     ON mv_party_dominance_cube(party_id);
     261CREATE INDEX idx_cube4_election  ON mv_party_dominance_cube(election_id);
     262CREATE INDEX idx_cube4_country   ON mv_party_dominance_cube(country_id);
     263CREATE INDEX idx_cube4_grouping  ON mv_party_dominance_cube(grouping_level);
     264CREATE INDEX idx_cube4_year      ON mv_party_dominance_cube(election_year);
     265CREATE INDEX idx_cube4_rank      ON mv_party_dominance_cube(rank_in_election);
     266CREATE UNIQUE INDEX idx_cube4_unique ON mv_party_dominance_cube(party_id, election_id, country_id, grouping_level);
     267}}}
     268
     269==== Примери на поддржани прашалници:
     270
     271„Каков е историскиот удел на гласови на ВМРО-ДПМНЕ на сите македонски парламентарни избори?"
     272
     273„Која партија постојано се рангира прва во Србија од 2012?"
     274
     275„Споредба на промената на гласови меѓу изборите 2020 и 2024 по партија"
     276
     277=== 5. mv_electoral_district_cube ===
     278
     279==== Опис:
     280Највисоко аналитички комплексната коцка — ја интегрира алокацијата на мандати по изборни единици со пресметките на D'Hondt методот на ниво на однапред агрегирање. Директно ја поддржува апликацијата за приказ на распределбата на мандати.
     281
     282==== Зошто е потребна:
     283Анализата на алокацијата на мандати е најскапиот пресметковен прашалник во системот. Бара спојување на electoral_district со election_participant, vote_result, polling_station и region, потоа примена на D'Hondt алгоритмот со CROSS JOIN LATERAL и generate_series. Коцката ги однапред пресметува алокациите на мандати за сите парламентарни избори и сите единици.
     284
     285==== Имплементација на D'Hondt во коцката:
     286
     287Пресметај гласови по ентитет по единица
     288
     289Филтрирај ентитети над 5% изборен праг
     290
     291Генерирај делители 1..seats_available по ентитет
     292
     293Пресметај количници: гласови / делител
     294
     295Рангирај ги сите количници по единица
     296
     297Додели мандати на топ-N количници
     298
     299Оваа логика се извршува еднаш при создавање на коцката и резултатите се складираат трајно.
     300
     301==== Димензии и Хиерархија:
     302|| Димензија || Хиерархија ||
     303|| Избори || election_type → election_year ||
     304|| Единица || district_id → district_name ||
     305|| Ентитет || entity_type → entity_name ||
     306
     307==== Мерки:
     308|| Мерка || Опис ||
     309|| total_votes || Гласови за ентитетот во единицата ||
     310|| total_district_votes || Вкупни гласови во единицата ||
     311|| vote_share_pct || Процент во рамки на единицата ||
     312|| seats_won || Мандати доделени со D'Hondt ||
     313|| entities_competing || Број на ентитети во единицата ||
     314
     315==== Нивоа генерирани со ROLLUP:
     316
     317Ниво 0 (најфино): мандати по ентитет по единица по избори
     318
     319Ниво 1: мандати по ентитет низ сите единици по избори
     320
     321Ниво 2: мандати по ентитет низ сите избори
     322
     323Ниво 3 (вкупно): сите ентитети, сите избори
     324
     325==== Создадени индекси:
     326{{{
     327CREATE INDEX idx_cube5_election ON mv_electoral_district_cube(election_id);
     328CREATE INDEX idx_cube5_district ON mv_electoral_district_cube(district_id);
     329CREATE INDEX idx_cube5_entity   ON mv_electoral_district_cube(entity_id);
     330CREATE INDEX idx_cube5_grouping ON mv_electoral_district_cube(grouping_level);
     331CREATE INDEX idx_cube5_seats    ON mv_electoral_district_cube(seats_won);
     332CREATE UNIQUE INDEX idx_cube5_unique ON mv_electoral_district_cube(election_id, district_id, entity_id, grouping_level);
     333}}}
     334
     335==== Примери на поддржани прашалници:
     336
     337„Колку мандати освои секој ентитет по единица на парламентарните избори 2024?"
     338
     339„Кој ентитет освоил највеќе мандати низ сите парламентарни избори историски?"
     340
     341„Како се сменила распределбата на мандати меѓу 2020 и 2024 во Скопскиот регион?"
     342
     343= Стратегија за освежување =
     344
     345Материјализираните погледи се снимки — не се ажурираат автоматски кога основните податоци се менуваат. Во производствен систем за избори, стратегијата за освежување би била:
     346
     347За активно гласање (ден на избори): освежување на секои 30 минути
     348
     349По затворање на изборите: едно финално освежување за официјални резултати
     350
     351Историски избори: без освежување, податоците се непроменливи
     352
     353Команди за освежување:
     354{{{
     355REFRESH MATERIALIZED VIEW CONCURRENTLY mv_election_results_cube;
     356REFRESH MATERIALIZED VIEW CONCURRENTLY mv_turnout_cube;
     357REFRESH MATERIALIZED VIEW CONCURRENTLY mv_candidate_cube;
     358REFRESH MATERIALIZED VIEW CONCURRENTLY mv_party_dominance_cube;
     359REFRESH MATERIALIZED VIEW CONCURRENTLY mv_electoral_district_cube;
     360}}}
     361
     362= Резиме =
     363
     364|| Коцка || Изворни табели || Димензии || Клучна мерка ||
     365|| mv_election_results_cube || vote_result, election, region, political_entity || Избори × Географија × Ентитет × Време || vote_share_pct ||
     366|| mv_turnout_cube || voter_election, voter, ballot, polling_station || Избори × Географија × Време || turnout_pct ||
     367|| mv_candidate_cube || candidate_party, candidate_list_item, candidate, person || Кандидат × Партија × Избори × Време || elections_contested ||
     368|| mv_party_dominance_cube || vote_result, political_entity, political_party || Партија × Избори × Географија × Време || rank_in_election ||
     369|| mv_electoral_district_cube || electoral_district, election_participant, vote_result || Единица × Ентитет × Избори || seats_won ||