== Документација за оптимизација [[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 on appointment(client_id,appointment_date) }}} бидејќи пребарувањето најчесто се врши според клиент и датум. === v_client_dashboard Овој view е наменет за почетниот екран на клиентот. Се користат две CTE структури: * `upcoming` * `recent_spend` Тие однапред ги пресметуваат: * идните термини * потрошувачката во последните 30 дена Потоа главниот SELECT само ги приклучува готовите агрегирани резултати. Ова е поефикасно отколку секој пат да се пресметуваат агрегатите за секој клиент одново. За овој view помага веќе креираниот индекс за погледот v_future_appointments_client_o: {{{ idx_appointment_client_future on appointment(client_id,appointment_date) }}} === v_staff_profile_m Овој view прикажува целосен профил на вработен. Наместо повторно да се пресметуваат оценки од `review`, се користи: {{{ mv_staff_avg_rating }}} што значително го намалува времето на извршување. Дополнително се користат два `LATERAL JOIN`: * агрегирање на услуги * агрегирање на улоги Само активни корисници учествуваат во резултатот: {{{ WHERE u.is_active = TRUE }}} За овој view е креиран индекс: {{{ idx_appointment_staff_rating on appointment(staff_id) }}} ==== mv_staff_avg_rating Ова е помошно Materialized View за погледот v_staff_profile_m. Наместо просечниот рејтинг да се пресметува секој пат кога се отвора профил на вработен, резултатот однапред се чува физички во базата. Предности: * многу побрзо читање * помал број JOIN операции * помал CPU трошок Се освежува преку: {{{ REFRESH MATERIALIZED VIEW CONCURRENTLY }}} што овозможува истовремено користење на податоците. За овој materialized view е креиран индекс: {{{ idx_appointment_staff_rating on appointment(staff_id) }}} Индексот и овозможува на базата да изврши Index Only Scan за групирање на термини по staff_id, избегнувајќи го бавното читање на целата табела appointment. Со тоа, операцијата за ажурирање (REFRESH) директно ги добива потребните податоци за AVG пресметката преку индексот, што ја намалува комплексноста на JOIN операцијата од линеарна во логаритамска. === v_invoice_detail_o Овој view е најдеталниот финансиски поглед. Главната табела е `invoice`, бидејќи фактурите се значително помалку од сите термини и услуги во системот. Се користат три `LATERAL JOIN`: * агрегација на услуги од терминот * агрегација на промо кодови * агрегација на улоги на вработениот Со ова секоја агрегација се извршува само за конкретната фактура. Овој пристап е поефикасен од глобални GROUP BY операции над целата база.