== Документација за оптимизација [[html(views_optimization_documentation.pdf)]] == Погледи == v_staff_daily_schedule Овој view служи за приказ на дневниот распоред на вработените. Табелата `appointment` е главната табела бидејќи ги содржи сите информации за закажаните термини. Се спојуваат: * `user` за име на вработениот. * `staff` за локацијата. * `company_location` за адресата. * `client` и `user` за информации за клиентот. Се користат два `LATERAL JOIN`: * Првиот ги агрегира сите улоги на вработениот од `staff_type`. * Вториот ги агрегира сите услуги поврзани со терминот од `appointment_service`. Филтерот: {{{ WHERE status <> 'cancelled' AND status <> 'completed' }}} се извршува најрано со што значително се намалува бројот на обработени термини. Функцијата `LEAD()` пресметува временски јаз помеѓу два последователни термини без дополнителни self-join операции. --- == v_staff_open_slots Овој view ги враќа сите слободни термини за закажување. Најпрво се креираат три мали агрегирани множества: * `staff_roles` * `staff_services` * `staff_rating` Со ова агрегирањето се извршува само еднаш. Главната табела е `staff_time_slot`. Филтрите: {{{ appointment_id IS NULL slot_start >= NOW() slot_start < NOW() + INTERVAL '30 days' }}} се применуваат веднаш. Потоа се прави JOIN со: * `staff` * `user` * `company_location` и LEFT JOIN со: * `blocked_time` за елиминација на блокираните термини. Со условот: {{{ b.block_id IS NULL }}} се задржуваат само реално достапните слотови. --- == v_companies_by_category Овој view овозможува пребарување компании според категорија и услуги. CTE `company_services` прво ги агрегира сите активни услуги по компанија. Филтерот: {{{ WHERE s.is_active = TRUE }}} се применува пред агрегацијата. Потоа се приклучуваат: * `company_company_category` * `company_category` * `company` На овој начин главниот SELECT работи со значително помал број редови. --- == v_staff_service_menu Овој view прикажува кои услуги ги нуди секој вработен. Во CTE `staff_service_ratings` однапред се пресметуваат: * просечна оцена * број на рецензии * број на извршувања Само термините со статус: {{{ completed }}} учествуваат во пресметката. Ова значително ја намалува количината на податоци бидејќи не се анализираат активни или откажани термини. --- == v_monthly_revenue_by_company Овој view служи за финансиски извештаи. Се користат само табелите: * `invoice` * `appointment` * `company_location` * `company` Бидејќи `invoice` е значително помала од `appointment_service`, пресметката е многу поефикасна. Сите финансиски агрегати: * SUM * AVG * COUNT се пресметуваат во една единствена GROUP BY операција. --- == v_future_appointments_client_o Овој view ги враќа идните термини на клиентите. Филтерот: {{{ appointment_date >= CURRENT_DATE status <> 'cancelled' }}} се применува уште на почетокот. Со тоа се елиминираат сите историски записи. Се користи `LATERAL JOIN` за агрегација на услугите на секој термин поединечно наместо глобално GROUP BY врз целата табела `appointment_service`. За овој view е креиран индекс: {{{ idx_appointment_client_future }}} бидејќи пребарувањето најчесто се врши според клиент и датум. --- == v_client_dashboard Овој view е наменет за почетниот екран на клиентот. Се користат две CTE структури: * `upcoming` * `recent_spend` Тие однапред ги пресметуваат: * идните термини * потрошувачката во последните 30 дена Потоа главниот SELECT само ги приклучува готовите агрегирани резултати. Ова е поефикасно отколку секој пат да се пресметуваат агрегатите за секој клиент одново. --- == mv_staff_avg_rating Ова е Materialized View. Наместо просечниот рејтинг да се пресметува секој пат кога се отвора профил на вработен, резултатот однапред се чува физички во базата. Предности: * многу побрзо читање * помал број JOIN операции * помал CPU трошок Се освежува преку: {{{ REFRESH MATERIALIZED VIEW CONCURRENTLY }}} што овозможува истовремено користење на податоците. --- == v_staff_profile_m Овој view прикажува целосен профил на вработен. Наместо повторно да се пресметуваат оценки од `review`, се користи: {{{ mv_staff_avg_rating }}} што значително го намалува времето на извршување. Дополнително се користат два `LATERAL JOIN`: * агрегирање на услуги * агрегирање на улоги Само активни корисници учествуваат во резултатот: {{{ WHERE u.is_active = TRUE }}} --- == v_invoice_detail_o Овој view е најдеталниот финансиски поглед. Главната табела е `invoice`, бидејќи фактурите се значително помалку од сите термини и услуги во системот. Се користат три `LATERAL JOIN`: * агрегација на услуги од терминот * агрегација на промо кодови * агрегација на улоги на вработениот Со ова секоја агрегација се извршува само за конкретната фактура. Овој пристап е поефикасен од глобални GROUP BY операции над целата база. --- == Индекси Во решението се користи минимален број индекси: * `idx_appointment_client_future` * индекс над `mv_staff_avg_rating` * `idx_appointment_staff_rating` Целта е да се избегне прекумерно индексирање кое би ја забавило работата при INSERT, UPDATE и DELETE операции. Избраните индекси покриваат само најчестите пребарувања: * идни термини по клиент * рејтинзи по вработен * профил на вработен Со ова се постигнува баланс помеѓу брзина на читање и брзина на запишување на податоци.