| | 1 | = Документација — OLAP = |
| | 2 | |
| | 3 | ---- |
| | 4 | |
| | 5 | == Преглед на архитектурата == |
| | 6 | |
| | 7 | Напредната тема го проширува постоечкиот OLTP модел (Hotel, Room, Reservation, Customer, Pet, Payment, итн.) со посебен '''OLAP слој''' во форма на '''ѕвезда шема (star schema)''': табели за димензиите во однос на три факт-табели, кои се користат за аналитички прашања (ROLLUP, CUBE, drill-down, window функции, pivoting, slicing). |
| | 8 | |
| | 9 | Причина за постоење на овој слој одделно од OLTP делот: OLTP шемата е оптимизирана за брзи, точни, секојдневни трансакциски прашања (пр. „резервациите на клиент X"). За разлика од OLTP, OLAP слојот е оптимизиран за тешки, аналитички прашања врз милиони редови (пр. „приход по хотел, по квартал, по вид миленче"). |
| | 10 | |
| | 11 | === Редослед на создавање на OLAP === |
| | 12 | |
| | 13 | {{{ |
| | 14 | 1. Dimensions.sql → димензии |
| | 15 | 2. FactReservation.sql → факт табела: резервации |
| | 16 | 3. FactOrderProduct.sql → факт табела: продажба на производи |
| | 17 | 4. FactServiceUsage.sql → факт табела: користење услуги |
| | 18 | 5. OLAP_Queries.sql → аналитички прашања |
| | 19 | }}} |
| | 20 | |
| | 21 | ---- |
| | 22 | |
| | 23 | == `Dimensions.sql` — Табели со димензии == |
| | 24 | |
| | 25 | === Цел === |
| | 26 | Ги гради '''табелите со димензии''' — податоци кои подоцна се користат за филтрирање и групирање во факт-табелите. Ова е стандарден чекор при градење на OLAP/dimensional модел врз постоечка OLTP база. |
| | 27 | |
| | 28 | === Содржина === |
| | 29 | |
| | 30 | ||= Табела =||= Тип =||= Опис =|| |
| | 31 | || `DimDate` || Type 1 || Датумска димензија, за периодот 2015–2027. `date_key` е во формат `YYYYMMDD` и служи и како partition key во факт-табелите. Содржи изведени атрибути: ден, месец, квартал, година, сезона, викенд. || |
| | 32 | || `DimHotel` || Type 1 || Хотели, преземени директно од `Hotel`. || |
| | 33 | || `DimRoomType` || Type 1 || Типови соби. || |
| | 34 | || `DimSpecies`, `DimBreed` || Type 1 || Видови и раси на миленчиња. || |
| | 35 | || `DimService` || Type 1 || Услуги, со додадена изведена колона `price_category` (Budget, Standard, Premium). || |
| | 36 | || `DimProduct` || Type 1 || Производи, со изведена `price_range` (Low, Mid, High). || |
| | 37 | || `DimRoom` || Type 2 || Соби — цената и типот можат да се менуваат со тек на време. || |
| | 38 | || `DimPet` || Type 2 || Миленчиња. Содржи изведена колона `age_group`. || |
| | 39 | || `DimCustomer` || Type 2 || Клиенти — адреса/локација. Содржи изведена колона `customer_segment` (New, Regular, VIP). || |
| | 40 | || `DimEmployee` || Type 2 || Вработени. || |
| | 41 | |
| | 42 | * '''Type 1''' — нема чување историја. |
| | 43 | * '''Type 2''' — табелите имаат `valid_from`, `valid_to`, `is_current` колони, наменети за чување историја на промени. |
| | 44 | |
| | 45 | ---- |
| | 46 | |
| | 47 | == `FactReservation.sql` — Факт табела за резервации == |
| | 48 | |
| | 49 | === Цел === |
| | 50 | Централна и најголема факт-табела — по еден ред за секоја резервација, со мерки (`total_cost`, `nights_stayed`, `num_services`, `has_delivery`) и референци кон сите релевантни димензии. |
| | 51 | |
| | 52 | === Партиционирање === |
| | 53 | Табелата е партиционирана според датум, со по една партиција за секоја година (2015–2027). Ова значи дека прашање филтрирано по конкретна година (пр. `WHERE d.year = 2022`) чита само од таа партиција, наместо да скенира сè. |
| | 54 | |
| | 55 | ---- |
| | 56 | |
| | 57 | == `FactOrderProduct.sql` — Факт табела за продажба на производи == |
| | 58 | |
| | 59 | === Цел === |
| | 60 | По еден ред за секој производ во секоја нарачка (mapping на `OrderProduct`), со мерки за количина, единечна цена, вкупна цена, статус на нарачка и статус на достава. |
| | 61 | |
| | 62 | === Партиционирање и индекси === |
| | 63 | Табелата е партиционирана според датум (година). |
| | 64 | |
| | 65 | ---- |
| | 66 | |
| | 67 | == `FactServiceUsage.sql` — Факт табела за услуги == |
| | 68 | |
| | 69 | === Цел === |
| | 70 | По еден ред за секое закажување услуга, со мерки за цена, времетраење и статус. |
| | 71 | |
| | 72 | === Партиционирање и индекси === |
| | 73 | Табелата е партиционирана според датум (година). |
| | 74 | |
| | 75 | ---- |
| | 76 | |
| | 77 | == `OLAP_Queries.sql` — Аналитички прашања == |
| | 78 | |
| | 79 | === Цел === |
| | 80 | Прашања кои ги демонстрираат стандардните OLAP операции и техники: '''ROLLUP''', '''CUBE''', '''drill-down''', '''window функции''', '''pivoting''' и '''slicing'''. |
| | 81 | |
| | 82 | === 1. Приходи — ROLLUP по хотел, година, квартал === |
| | 83 | Хиерархиско групирање: `GROUP BY ROLLUP(h.hotel_name, d.year, d.quarter)` генерира детален ред за секоја комбинација, плус меѓусуми на секое повисоко ниво (по хотел+година, по хотел, вкупно). |
| | 84 | |
| | 85 | === 2. Occupancy Rate по хотел и сезона — CUBE === |
| | 86 | `GROUP BY CUBE(h.hotel_name, d.season)` генерира '''сите можни комбинации''' на групирање, бидејќи хотел и сезона се независни димензии без природна хиерархија меѓу нив. |
| | 87 | |
| | 88 | === 3. Drill Down — Наоѓање каде паѓа приходот === |
| | 89 | Постепено навлегување од општо кон конкретно: |
| | 90 | 1. Открива година со нисок приход (годишните тотали се споредуваат меѓу себе преку self-join — секоја година е споена со редот за претходната година, наместо со `LAG()`). |
| | 91 | 2. По хотел, во таа година — открива хотел со низок приход. |
| | 92 | 3. По вид миленче, во тој хотел/година — открива вид кој придонел за приходот. |
| | 93 | 4. По месец, за тој вид/хотел/година — крајно ниво на детали. |
| | 94 | |
| | 95 | Секој чекор го стеснува опсегот со `WHERE`, врз основа на она што е откриено во претходниот чекор. |
| | 96 | |
| | 97 | === 4. Топ услуги по приход — Window Functions === |
| | 98 | Рангира услуги одделно во секој хотел. Вгнездена агрегација пресметува процент од вкупниот приход на хотелот. |
| | 99 | |
| | 100 | === 5. Customer Lifetime Value — највредни клиенти === |
| | 101 | Два одделни ранга во исто прашање: глобален и по сегмент (партиција). |
| | 102 | |
| | 103 | === 6. Продажба на производи — CUBE по категорија, хотел и ценовен опсег === |
| | 104 | `CUBE(dp.category_name, h.hotel_name, dp.price_range)` со три независни димензии генерира 8 можни комбинации на групирање — сите комбинации од: категорија, хотел и ценовен опсег. |
| | 105 | |
| | 106 | === 7. Pivoting — типови соби како колони === |
| | 107 | Ги претвора вредностите на димензијата `room_type` во посебни колони (наместо редови), со цел приходот по секој тип соба да се спореди во еден ред по хотел. Реализирано преку условна агрегација (`SUM(CASE WHEN ... THEN ... END)`), бидејќи Postgres нема вградена `PIVOT` синтакса. |
| | 108 | |
| | 109 | |
| | 110 | === 8. Slicing — фиксирање вредности на димензии === |
| | 111 | Slicing значи фиксирање на вредноста на '''една''' димензија. Во аналитичките прашања се фиксира вредноста на хотелот - hotel_name = 'Fur Haven' и се прави преглед на преостанатите димензии. Во аналитичките прашања се прави и ''dicing'' (се фиксираат вредности на '''повеќе''' димензии истовремено): хотел + сезона + вид миленче. |
| | 112 | |
| | 113 | |