Changes between Initial Version and Version 1 of Indexes


Ignore:
Timestamp:
08/18/25 20:43:47 (2 months ago)
Author:
221071
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Indexes

    v1 v1  
     1= Индекси за оптимизација на напредни извештаи
     2
     3
     4== Анализа на извештаи и потребни индекси == #анализа
     5
     6=== 1. Индекси за извештај за процент на изнајмени недвижности во однос на објавени огласи за секоја година.=== #извештај1
     7
     8Овој извештај користи и извршува операции со:
     9 * `EXTRACT(YEAR FROM available_from)` на Listing табела
     10 * `EXTRACT(YEAR FROM l.start_date)` на Lease табела 
     11 * JOIN помеѓу Lease и Listing преку listing_id
     12
     13'''Потребни индекси:'''
     14
     15{{{#!sql
     16-- За брзо филтрирање по година на објавување
     17CREATE INDEX IF NOT EXISTS idx_listing_available_from_year ON Listing(EXTRACT(YEAR FROM available_from));
     18
     19-- За брзо филтрирање по година на започнување на изнајмувањето
     20CREATE INDEX IF NOT EXISTS idx_lease_start_date_year ON Lease(EXTRACT(YEAR FROM start_date));
     21
     22-- За оптимизација на JOIN операциите
     23CREATE INDEX IF NOT EXISTS idx_lease_listing_id ON Lease(listing_id);
     24
     25-- Композитен индекс за подобра оптимизација на временски операции
     26CREATE INDEX IF NOT EXISTS idx_listing_available_from ON Listing(available_from);
     27CREATE INDEX IF NOT EXISTS idx_lease_start_date ON Lease(start_date);
     28}}}
     29
     30=== 2. Извештај за раст на приходи по град во однос на претходната година  === #извештај2
     31
     32Овој извештај е особено сложен бидејќи користи повеќе JOIN операции и агрегатни функции со временски филтрирања.
     33
     34'''Критични операции:'''
     35 * JOIN низа: Payment → Lease → Listing → Unit → Property → Address
     36 * WHERE услов: `p.status = 'завршено'`
     37 * GROUP BY со `EXTRACT(YEAR FROM p.payment_date)`
     38
     39'''Потребни индекси:'''
     40
     41{{{#!sql
     42-- За брзо филтрирање на успешни плаќања
     43CREATE INDEX IF NOT EXISTS idx_payment_status ON Payment(status);
     44
     45-- За временски анализи на плаќања
     46CREATE INDEX IF NOT EXISTS idx_payment_date_year ON Payment(EXTRACT(YEAR FROM payment_date));
     47CREATE INDEX IF NOT EXISTS idx_payment_date ON Payment(payment_date);
     48
     49-- За оптимизација на JOIN операциите
     50CREATE INDEX IF NOT EXISTS idx_payment_lease_id ON Payment(lease_id);
     51CREATE INDEX IF NOT EXISTS idx_listing_unit_id ON Listing(unit_id);
     52CREATE INDEX IF NOT EXISTS idx_unit_property_id ON Unit(property_id);
     53CREATE INDEX IF NOT EXISTS idx_property_address_id ON Property(address_id);
     54
     55-- За групирање по град
     56CREATE INDEX IF NOT EXISTS idx_address_city ON Address(city);
     57
     58-- Композитен индекс за плаќања со статус и датум
     59CREATE INDEX IF NOT EXISTS idx_payment_status_date ON Payment(status, payment_date);
     60}}}
     61
     62=== 3. Детален месечен извештај за издавачите  === #извештај3
     63
     64Овој извештај е најсложен и користи повеќе CTE изрази со различни временски периоди.
     65
     66'''Клучни операции:'''
     67 * Филтрирање по landlord_id
     68 * Временски операции со start_date и end_date
     69 * Проверка на статус на плаќања
     70
     71'''Потребни индекси:'''
     72
     73{{{#!sql
     74-- За брза идентификација на изадавачите
     75CREATE INDEX IF NOT EXISTS idx_lease_landlord_id ON Lease(landlord_id);
     76
     77-- За временски филтрирања на изнајмувања
     78CREATE INDEX IF NOT EXISTS idx_lease_start_date ON Lease(start_date);
     79CREATE INDEX IF NOT EXISTS idx_lease_end_date ON Lease(end_date);
     80
     81-- Композитен индекс за временски период на договор
     82CREATE INDEX IF NOT EXISTS idx_lease_dates ON Lease(start_date, end_date);
     83
     84-- За филтрирање активни договори
     85CREATE INDEX IF NOT EXISTS idx_lease_landlord_dates ON Lease(landlord_id, start_date, end_date);
     86
     87-- За сервисни барања
     88CREATE INDEX IF NOT EXISTS idx_service_request_status ON ServiceRequest(status);
     89CREATE INDEX IF NOT EXISTS idx_service_request_lease_id ON ServiceRequest(lease_id);
     90
     91-- За UserD табела (landlord профили)
     92CREATE INDEX IF NOT EXISTS idx_userd_id ON UserD(id);
     93}}}
     94
     95=== 4. Извештај за платежна историја на станари  === #извештај4
     96
     97Фокусиран на tenant_id и различни статуси на плаќања.
     98
     99'''Потребни индекси:'''
     100
     101{{{#!sql
     102-- За идентификација на станари
     103CREATE INDEX IF NOT EXISTS idx_lease_tenant_id ON Lease(tenant_id);
     104CREATE INDEX IF NOT EXISTS idx_tenant_profile_id ON TenantProfile(id);
     105
     106-- За анализа на плаќања по статус
     107CREATE INDEX IF NOT EXISTS idx_payment_status ON Payment(status);
     108CREATE INDEX IF NOT EXISTS idx_payment_lease_status ON Payment(lease_id, status);
     109
     110-- За пресметка на просечна кирија
     111CREATE INDEX IF NOT EXISTS idx_lease_rent_amount ON Lease(rent_amount);
     112
     113-- За временска анализа на изнајмувања
     114CREATE INDEX IF NOT EXISTS idx_lease_tenant_dates ON Lease(tenant_id, start_date, end_date);
     115}}}
     116
     117=== 5. Извештај за сервисни барања по општина  === #извештај5
     118
     119Анализира сервисни барања со географска и категориска сегментација.
     120
     121'''Потребни индекси:'''
     122
     123{{{#!sql
     124-- За категоризација на сервисни барања
     125CREATE INDEX IF NOT EXISTS idx_service_request_category ON ServiceRequest(service_category_id);
     126
     127-- За временска анализа на барања
     128CREATE INDEX IF NOT EXISTS idx_service_request_date ON ServiceRequest(request_date);
     129
     130-- За анализа на одржување
     131CREATE INDEX IF NOT EXISTS idx_maintenance_log_service_request ON MaintenanceLog(service_request_id);
     132CREATE INDEX IF NOT EXISTS idx_maintenance_log_date ON MaintenanceLog(maintenance_date);
     133
     134-- За географска анализа
     135CREATE INDEX IF NOT EXISTS idx_address_municipality ON Address(municipality);
     136CREATE INDEX IF NOT EXISTS idx_address_municipality_city ON Address(municipality, city);
     137
     138-- Композитен индекс за временска анализа на сервиси
     139CREATE INDEX IF NOT EXISTS idx_service_request_status_date ON ServiceRequest(status, request_date);
     140}}}
     141
     142=== 6. Анализа на пазарни трендови === #извештај6
     143
     144Анализира понуда и побарувачка по регион и тип на недвижност.
     145
     146'''Потребни индекси:'''
     147
     148{{{#!sql
     149-- За анализа по тип на недвижност
     150CREATE INDEX IF NOT EXISTS idx_property_type_id ON Property(property_type_id);
     151
     152-- За статус на огласи
     153CREATE INDEX IF NOT EXISTS idx_listing_status ON Listing(status);
     154
     155-- За пресметка на цена по квадратен метар
     156CREATE INDEX IF NOT EXISTS idx_unit_rent_area ON Unit(rent_amount, area_sq_m);
     157
     158-- За заинтересираност
     159CREATE INDEX IF NOT EXISTS idx_interested_listing_id ON Interested(listing_id);
     160CREATE INDEX IF NOT EXISTS idx_interested_tenant_profile ON Interested(tenant_profile_id);
     161
     162-- Композитен индекс за пазарна анализа
     163CREATE INDEX IF NOT EXISTS idx_listing_unit_status ON Listing(unit_id, status);
     164}}}
     165
     166== Тестирање на индексите со EXPLAIN ANALYZE == #тестирање
     167
     168За да се провери ефикасноста на индексите, можеме да користиме EXPLAIN ANALYZE:
     169
     170{{{#!sql
     171-- Пример за тестирање на Извештај 4
     172EXPLAIN ANALYZE
     173WITH TenantPaymentStats AS (
     174    SELECT
     175        t.id as tenant_id,
     176        CONCAT(u.first_name, ' ', u.last_name) as tenant_name,
     177        u.rating as tenant_rating,
     178        COUNT(DISTINCT le.id) as total_leases,
     179        COUNT(DISTINCT pay.id) as total_payments,
     180        SUM(CASE WHEN pay.status = 'завршено' THEN pay.amount ELSE 0 END) as total_paid,
     181        SUM(CASE WHEN pay.status = 'доцнење' THEN pay.amount ELSE 0 END) as late_payments_amount,
     182        COUNT(CASE WHEN pay.status = 'доцнење' THEN 1 END) as late_payment_count,
     183        COUNT(CASE WHEN pay.status = 'во тек' THEN 1 END) as pending_payment_count,
     184        AVG(le.rent_amount) as avg_rent_amount,
     185        MIN(le.start_date) as first_lease_date,
     186        MAX(le.end_date) as latest_lease_end
     187    FROM TenantProfile t
     188    JOIN UserD u ON t.id = u.id
     189    LEFT JOIN Lease le ON t.id = le.tenant_id
     190    LEFT JOIN Payment pay ON le.id = pay.lease_id
     191    GROUP BY t.id, u.first_name, u.last_name, u.rating
     192)
     193SELECT
     194    tenant_id,
     195    tenant_name,
     196    tenant_rating,
     197    total_leases,
     198    total_payments,
     199    total_paid,
     200    late_payments_amount,
     201    late_payment_count,
     202    pending_payment_count,
     203    ROUND((late_payment_count * 100.0 / NULLIF(total_payments, 0)), 2) as late_payment_percentage,
     204    avg_rent_amount,
     205    first_lease_date,
     206    latest_lease_end,
     207    CASE
     208        WHEN late_payment_count = 0 THEN 'Одличен'
     209        WHEN late_payment_count <= 2 THEN 'Добар'
     210        WHEN late_payment_count <= 5 THEN 'Среден'
     211        ELSE 'Ризичен'
     212    END as payment_reliability_score
     213FROM TenantPaymentStats
     214WHERE total_leases > 0
     215ORDER BY late_payment_percentage ASC, total_paid DESC;
     216
     217}}}
     218
     219'''Што да бараме во резултатот:'''
     220 * '''Index Scan''' наместо '''Seq Scan''' - значи дека индексот се користи
     221 * '''Nested Loop''' со '''Index Scan''' на внатрешната страна на JOIN
     222 * '''Execution time''' треба да биде значително намален
     223
     224
     225
     226