= Документација — OLAP = ---- == Преглед на архитектурата == Напредната тема го проширува постоечкиот OLTP модел (Hotel, Room, Reservation, Customer, Pet, Payment, итн.) со посебен '''OLAP слој''' во форма на '''ѕвезда шема (star schema)''': табели за димензиите во однос на три факт-табели, кои се користат за аналитички прашања (ROLLUP, CUBE, drill-down, window функции, pivoting, slicing). Причина за постоење на овој слој одделно од OLTP делот: OLTP шемата е оптимизирана за брзи, точни, секојдневни трансакциски прашања (пр. „резервациите на клиент X"). За разлика од OLTP, OLAP слојот е оптимизиран за тешки, аналитички прашања врз милиони редови (пр. „приход по хотел, по квартал, по вид миленче"). === Редослед на создавање на OLAP === {{{ 1. Dimensions.sql → димензии 2. FactReservation.sql → факт табела: резервации 3. FactOrderProduct.sql → факт табела: продажба на производи 4. FactServiceUsage.sql → факт табела: користење услуги 5. OLAP_Queries.sql → аналитички прашања }}} ---- == `Dimensions.sql` — Табели со димензии == === Цел === Ги гради '''табелите со димензии''' — податоци кои подоцна се користат за филтрирање и групирање во факт-табелите. Ова е стандарден чекор при градење на OLAP/dimensional модел врз постоечка OLTP база. === Содржина === ||= Табела =||= Тип =||= Опис =|| || `DimDate` || Type 1 || Датумска димензија, за периодот 2015–2027. `date_key` е во формат `YYYYMMDD` и служи и како partition key во факт-табелите. Содржи изведени атрибути: ден, месец, квартал, година, сезона, викенд. || || `DimHotel` || Type 1 || Хотели, преземени директно од `Hotel`. || || `DimRoomType` || Type 1 || Типови соби. || || `DimSpecies`, `DimBreed` || Type 1 || Видови и раси на миленчиња. || || `DimService` || Type 1 || Услуги, со додадена изведена колона `price_category` (Budget, Standard, Premium). || || `DimProduct` || Type 1 || Производи, со изведена `price_range` (Low, Mid, High). || || `DimRoom` || Type 2 || Соби — цената и типот можат да се менуваат со тек на време. || || `DimPet` || Type 2 || Миленчиња. Содржи изведена колона `age_group`. || || `DimCustomer` || Type 2 || Клиенти — адреса/локација. Содржи изведена колона `customer_segment` (New, Regular, VIP). || || `DimEmployee` || Type 2 || Вработени. || * '''Type 1''' — нема чување историја. * '''Type 2''' — табелите имаат `valid_from`, `valid_to`, `is_current` колони, наменети за чување историја на промени. ---- == `FactReservation.sql` — Факт табела за резервации == === Цел === Централна и најголема факт-табела — по еден ред за секоја резервација, со мерки (`total_cost`, `nights_stayed`, `num_services`, `has_delivery`) и референци кон сите релевантни димензии. === Партиционирање === Табелата е партиционирана според датум, со по една партиција за секоја година (2015–2027). Ова значи дека прашање филтрирано по конкретна година (пр. `WHERE d.year = 2022`) чита само од таа партиција, наместо да скенира сè. ---- == `FactOrderProduct.sql` — Факт табела за продажба на производи == === Цел === По еден ред за секој производ во секоја нарачка (mapping на `OrderProduct`), со мерки за количина, единечна цена, вкупна цена, статус на нарачка и статус на достава. === Партиционирање и индекси === Табелата е партиционирана според датум (година). ---- == `FactServiceUsage.sql` — Факт табела за услуги == === Цел === По еден ред за секое закажување услуга, со мерки за цена, времетраење и статус. === Партиционирање и индекси === Табелата е партиционирана според датум (година). ---- == `OLAP_Queries.sql` — Аналитички прашања == === Цел === Прашања кои ги демонстрираат стандардните OLAP операции и техники: '''ROLLUP''', '''CUBE''', '''drill-down''', '''window функции''', '''pivoting''' и '''slicing'''. === 1. Приходи — ROLLUP по хотел, година, квартал === Хиерархиско групирање: `GROUP BY ROLLUP(h.hotel_name, d.year, d.quarter)` генерира детален ред за секоја комбинација, плус меѓусуми на секое повисоко ниво (по хотел+година, по хотел, вкупно). === 2. Occupancy Rate по хотел и сезона — CUBE === `GROUP BY CUBE(h.hotel_name, d.season)` генерира '''сите можни комбинации''' на групирање, бидејќи хотел и сезона се независни димензии без природна хиерархија меѓу нив. === 3. Drill Down — Наоѓање каде паѓа приходот === Постепено навлегување од општо кон конкретно: 1. Открива година со нисок приход (годишните тотали се споредуваат меѓу себе преку self-join — секоја година е споена со редот за претходната година, наместо со `LAG()`). 2. По хотел, во таа година — открива хотел со низок приход. 3. По вид миленче, во тој хотел/година — открива вид кој придонел за приходот. 4. По месец, за тој вид/хотел/година — крајно ниво на детали. Секој чекор го стеснува опсегот со `WHERE`, врз основа на она што е откриено во претходниот чекор. === 4. Топ услуги по приход — Window Functions === Рангира услуги одделно во секој хотел. Вгнездена агрегација пресметува процент од вкупниот приход на хотелот. === 5. Customer Lifetime Value — највредни клиенти === Два одделни ранга во исто прашање: глобален и по сегмент (партиција). === 6. Продажба на производи — CUBE по категорија, хотел и ценовен опсег === `CUBE(dp.category_name, h.hotel_name, dp.price_range)` со три независни димензии генерира 8 можни комбинации на групирање — сите комбинации од: категорија, хотел и ценовен опсег. === 7. Pivoting — типови соби како колони === Ги претвора вредностите на димензијата `room_type` во посебни колони (наместо редови), со цел приходот по секој тип соба да се спореди во еден ред по хотел. Реализирано преку условна агрегација (`SUM(CASE WHEN ... THEN ... END)`), бидејќи Postgres нема вградена `PIVOT` синтакса. === 8. Slicing — фиксирање вредности на димензии === Slicing значи фиксирање на вредноста на '''една''' димензија. Во аналитичките прашања се фиксира вредноста на хотелот - hotel_name = 'Fur Haven' и се прави преглед на преостанатите димензии. Во аналитичките прашања се прави и ''dicing'' (се фиксираат вредности на '''повеќе''' димензии истовремено): хотел + сезона + вид миленче.