Changes between Version 9 and Version 10 of Optimization


Ignore:
Timestamp:
06/14/26 21:23:31 (6 days ago)
Author:
231184
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Optimization

    v9 v10  
    55Rezervo е систем за резервации кај занаетчии и даватели на услуги, каде што корисниците можат да пребаруваат достапни термини, да закажуваат, менуваат или откажуваат резервации, како и да оставаат рецензии за услугите.
    66
    7 За мерење на времињата се користи `EXPLAIN ANALYZE`. Кај секој поглед прво се брише индексот доколку постои, потоа се мери времето без индекс, па се креира индексот и повторно се мери времето со индекс. Како резултат во документацијата се зема вредноста `Execution Time`.
     7За мерење на времињата се користи `EXPLAIN ANALYZE`. Кај секој поглед прво се мери времето без индекс, потоа се креира индексот и повторно се мери времето со индекс. Како резултат во документацијата се зема вредноста `Execution Time`.
    88
    99== 1. Анализа на поглед customer_appointments_view, преглед на резервации за конкретен корисник ==
     
    1919}}}
    2020
    21 За точно да го измериме времето пред и после оптимизација, прво го бришеме индексот ако веќе постои, потоа го извршуваме прашалникот без индекс, па го креираме индексот и повторно го извршуваме истиот прашалник.
    22 
    23 {{{
    24 
    25 -- 1. Мерење без индекс
     21За оптимизација го тестираме истиот прашалник пред и после додавање на индексот.
     22
     23{{{
     24-- 3. Мерење без индекс
    2625EXPLAIN ANALYZE
    2726SELECT *
     
    2928WHERE customer_id = 100;
    3029
    31 -- 2. Креирање на индекс
     30-- 4. Креирање на индекс
    3231CREATE INDEX IF NOT EXISTS idx_appointment_customer_not_cancelled
    3332ON appointment(customer_id)
     
    4544->  Hash Join  (cost=87.68..126.58 rows=5 width=97) (actual time=3.625..4.537 rows=6 loops=1)
    4645Hash Cond: (a.service_id = s.service_id)
    47 ->  Nested Loop  (cost=83.41..122.30 rows=5 width=86) (actual time=3.361..4.267 rows=6 loops=1)
    48 ->  Index Scan using pk_customer on customer c
    49 Index Cond: (customer_id = 100)
    50 ->  Hash Join
    51 Hash Cond: (e.employee_id = a.employee_id)
    52 ->  Seq Scan on employee e
    53 ->  Hash
    54 ->  Hash Right Join
    55 ->  Seq Scan on business_location bl
    56 ->  Hash
    57 ->  Hash Join
    58 ->  Seq Scan on business b
    59 ->  Hash
    6046->  Index Scan using idx_appointment_customer_profile on appointment a
    6147Index Cond: (customer_id = 100)
    6248Filter: ((status)::text <> 'cancelled'::text)
    6349Rows Removed by Filter: 1
    64 ->  Index Scan using pk_time_slot on time_slot ts
    65 Index Cond: (slot_id = a.slot_id)
    6650
    6751Planning Time: 8.862 ms
     
    6953}}}
    7054
    71 Во овој план се гледа дека за табелата `appointment` се користи индексот `idx_appointment_customer_profile`, но сепак дополнително се применува филтерот:
     55Во овој план се гледа дека за табелата `appointment` се користи индекс според `customer_id`, но сепак дополнително се применува филтерот:
    7256
    7357{{{
     
    9579{{{
    9680Nested Loop  (cost=87.54..168.32 rows=5 width=151) (actual time=0.576..0.714 rows=6 loops=1)
    97 ->  Nested Loop  (cost=87.11..125.99 rows=5 width=97) (actual time=0.557..0.672 rows=6 loops=1)
    98 ->  Index Scan using pk_customer on customer c
    99 Index Cond: (customer_id = 100)
    100 ->  Hash Join
    101 Hash Cond: (e.employee_id = a.employee_id)
    102 ->  Seq Scan on employee e
    103 ->  Hash
    104 ->  Hash Right Join
    105 ->  Seq Scan on business_location bl
    106 ->  Hash
    107 ->  Hash Join
    108 ->  Seq Scan on business b
    109 ->  Hash
    110 ->  Hash Join
    111 Hash Cond: (s.service_id = a.service_id)
    112 ->  Seq Scan on service s
    113 ->  Hash
    11481->  Index Scan using idx_appointment_customer_not_cancelled on appointment a
    11582Index Cond: (customer_id = 100)
    116 ->  Index Scan using pk_time_slot on time_slot ts
    117 Index Cond: (slot_id = a.slot_id)
    11883
    11984Planning Time: 3.150 ms
     
    150115}}}
    151116
    152 За точно мерење на времето пред и после оптимизација, прво го бришеме индексот доколку постои, потоа го извршуваме прашалникот без индекс, па го креираме индексот и повторно го извршуваме истиот прашалник.
    153 
    154 {{{
    155 -- 1. Бришење на индексот ако веќе постои
    156 DROP INDEX IF EXISTS idx_time_slot_available_business_date;
    157 
    158 -- 2. Освежување на статистиките
    159 ANALYZE time_slot;
    160 
     117За оптимизација го тестираме истиот прашалник пред и после додавање на индексот.
     118
     119{{{
    161120-- 3. Мерење без индекс
    162121EXPLAIN ANALYZE
     
    170129ON time_slot(business_id, date)
    171130WHERE is_available = TRUE;
    172 
    173 -- 5. Освежување на статистиките
    174 ANALYZE time_slot;
    175 
    176 -- 6. Мерење со индекс
    177 EXPLAIN ANALYZE
    178 SELECT *
    179 FROM available_slots
    180 WHERE business_id = 1
    181 AND date = CURRENT_DATE;
    182131}}}
    183132
     
    190139{{{
    191140Nested Loop  (cost=1001.27..479269.43 rows=21 width=100) (actual time=7156.545..7157.282 rows=48 loops=1)
    192 ->  Nested Loop  (cost=1001.13..479265.89 rows=21 width=74) (actual time=7156.537..7157.258 rows=48 loops=1)
    193 Join Filter: ((es.employee_id = ts.employee_id) AND (es.service_id = bs.service_id))
    194 ->  Nested Loop
    195 ->  Nested Loop
    196 ->  Nested Loop
    197 ->  Index Scan using uq_business_service_business_service on business_service bs
    198 Index Cond: (business_id = 1)
    199 Filter: is_active
    200 ->  Materialize
    201 ->  Index Scan using pk_business on business b
    202 Index Cond: (business_id = 1)
    203 ->  Materialize
    204141->  Gather
    205142Workers Planned: 2
     
    208145Filter: (is_available AND (business_id = 1) AND (date = CURRENT_DATE))
    209146Rows Removed by Filter: 6666651
    210 ->  Memoize
    211 Cache Key: ts.employee_id
    212 ->  Index Scan using pk_employee on employee e
    213 Index Cond: (employee_id = ts.employee_id)
    214 ->  Index Only Scan using uq_employee_service_employee_service on employee_service es
    215 Index Cond: (employee_id = e.employee_id)
    216 Heap Fetches: 0
    217 ->  Index Scan using pk_service on service s
    218 Index Cond: (service_id = es.service_id)
    219147
    220148Planning Time: 4.741 ms
     
    250178{{{
    251179Nested Loop  (cost=69.25..256.19 rows=35 width=100) (actual time=0.364..0.485 rows=48 loops=1)
    252 ->  Nested Loop  (cost=69.10..250.31 rows=35 width=74) (actual time=0.359..0.443 rows=48 loops=1)
    253 ->  Index Scan using pk_business on business b
    254 Index Cond: (business_id = 1)
    255 ->  Hash Join
    256 Hash Cond: (es.service_id = bs.service_id)
    257 ->  Nested Loop
    258 Join Filter: (es.employee_id = ts.employee_id)
    259 ->  Hash Join
    260 Hash Cond: (ts.employee_id = e.employee_id)
    261180->  Index Scan using idx_time_slot_available_business_date on time_slot ts
    262181Index Cond: ((business_id = 1) AND (date = CURRENT_DATE))
    263 ->  Hash
    264 ->  Seq Scan on employee e
    265 ->  Index Only Scan using uq_employee_service_employee_service on employee_service es
    266 Index Cond: (employee_id = e.employee_id)
    267 Heap Fetches: 0
    268 ->  Hash
    269 ->  Bitmap Heap Scan on business_service bs
    270 Recheck Cond: (business_id = 1)
    271 Filter: is_active
    272 ->  Bitmap Index Scan on uq_business_service_business_service
    273 Index Cond: (business_id = 1)
    274 ->  Index Scan using pk_service on service s
    275 Index Cond: (service_id = es.service_id)
    276182
    277183Planning Time: 2.741 ms
     
    307213}}}
    308214
    309 За точно мерење на времето пред и после оптимизација, прво го бришеме индексот доколку постои, потоа го извршуваме прашалникот без индекс, па го креираме индексот и повторно го извршуваме истиот прашалник.
    310 
    311 {{{
    312 -- 1. Бришење на индексот ако веќе постои
    313 DROP INDEX IF EXISTS idx_review_rating_details;
    314 
    315 -- 2. Освежување на статистиките
    316 ANALYZE review;
    317 
     215За оптимизација го тестираме истиот прашалник пред и после додавање на индексот.
     216
     217{{{
    318218-- 3. Мерење без индекс
    319219EXPLAIN ANALYZE
     
    325225CREATE INDEX IF NOT EXISTS idx_review_rating_details
    326226ON review(rating);
    327 
    328 -- 5. Освежување на статистиките
    329 ANALYZE review;
    330 
    331 -- 6. Мерење со индекс
    332 EXPLAIN ANALYZE
    333 SELECT *
    334 FROM review_details
    335 WHERE rating = 5;
    336227}}}
    337228
     
    344235{{{
    345236Hash Join  (cost=39.52..111924.47 rows=1006495 width=35) (actual time=0.710..344.505 rows=1000001 loops=1)
    346 Hash Cond: (r.business_id = b.business_id)
    347237->  Seq Scan on review r  (cost=0.00..109231.71 rows=1006495 width=27) (actual time=0.169..259.457 rows=1000001 loops=1)
    348238Filter: (rating = 5)
    349239Rows Removed by Filter: 4000000
    350 ->  Hash  (cost=27.01..27.01 rows=1001 width=16) (actual time=0.528..0.528 rows=1001 loops=1)
    351 Buckets: 1024  Batches: 1  Memory Usage: 59kB
    352 ->  Seq Scan on business b  (cost=0.00..27.01 rows=1001 width=16) (actual time=0.020..0.311 rows=1001 loops=1)
    353240
    354241Planning Time: 2.849 ms
     
    383270{{{
    384271Hash Join  (cost=11246.93..73210.68 rows=1006319 width=35) (actual time=40.929..223.700 rows=1000001 loops=1)
    385 Hash Cond: (r.business_id = b.business_id)
    386 ->  Bitmap Heap Scan on review r  (cost=11207.40..70518.39 rows=1006319 width=27) (actual time=40.699..142.119 rows=1000001 loops=1)
     272->  Bitmap Heap Scan on review r
    387273Recheck Cond: (rating = 5)
    388 Heap Blocks: exact=46732
    389 ->  Bitmap Index Scan on idx_review_rating_details  (cost=0.00..10955.83 rows=1006319 width=0) (actual time=33.958..33.958 rows=1000001 loops=1)
     274->  Bitmap Index Scan on idx_review_rating_details
    390275Index Cond: (rating = 5)
    391 ->  Hash  (cost=27.01..27.01 rows=1001 width=16) (actual time=0.220..0.221 rows=1001 loops=1)
    392 Buckets: 1024  Batches: 1  Memory Usage: 59kB
    393 ->  Seq Scan on business b  (cost=0.00..27.01 rows=1001 width=16) (actual time=0.005..0.113 rows=1001 loops=1)
    394276
    395277Planning Time: 0.593 ms
     
    434316}}}
    435317
    436 За точно мерење на времето пред и после оптимизација, прво ги бришеме индексите доколку постојат, потоа го извршуваме прашалникот без индекс, па го креираме индексот и повторно го извршуваме истиот прашалник.
    437 
    438 {{{
    439 -- 1. Бришење на индексот ако веќе постои
    440 DROP INDEX IF EXISTS idx_review_customer_profile;
    441 
    442 -- Ако случајно е креиран и овој индекс, го бришеме и него
    443 DROP INDEX IF EXISTS idx_appointment_customer_profile;
    444 
    445 -- 2. Освежување на статистиките
    446 ANALYZE appointment;
    447 ANALYZE review;
    448 
     318За оптимизација го тестираме истиот прашалник пред и после додавање на индексот.
     319
     320{{{
    449321-- 3. Мерење без индекс
    450322EXPLAIN ANALYZE
     
    456328CREATE INDEX IF NOT EXISTS idx_review_customer_profile
    457329ON review(customer_id, rating);
    458 
    459 -- 5. Освежување на статистиките
    460 ANALYZE appointment;
    461 ANALYZE review;
    462 
    463 -- 6. Мерење со индекс
    464 EXPLAIN ANALYZE
    465 SELECT *
    466 FROM customer_profile_view
    467 WHERE customer_id = 100;
    468330}}}
    469331
     
    476338{{{
    477339GroupAggregate  (cost=147561.37..147562.12 rows=25 width=117) (actual time=545.746..546.153 rows=1 loops=1)
    478 Group Key: u.user_id
    479 ->  Sort  (cost=147561.37..147561.43 rows=25 width=77) (actual time=545.501..545.909 rows=49 loops=1)
    480 Sort Key: u.user_id, a.appointment_id
    481 Sort Method: quicksort  Memory: 29kB
    482 ->  Nested Loop Left Join  (cost=2000.85..147560.79 rows=25 width=77) (actual time=4.673..545.848 rows=49 loops=1)
    483 ->  Nested Loop Left Join  (cost=1000.85..73786.27 rows=5 width=69) (actual time=4.562..382.328 rows=7 loops=1)
    484 ->  Nested Loop  (cost=0.85..16.89 rows=1 width=53) (actual time=1.813..1.815 rows=1 loops=1)
    485 ->  Index Scan using pk_customer on customer c
    486 Index Cond: (customer_id = 100)
    487 ->  Index Scan using pk_user on "user" u
    488 Index Cond: (user_id = c.user_id)
    489 ->  Gather
    490 Workers Planned: 2
    491 Workers Launched: 2
    492340->  Parallel Seq Scan on appointment a
    493341Filter: (customer_id = 100)
    494342Rows Removed by Filter: 1666665
    495 ->  Materialize
    496 ->  Gather
    497 Workers Planned: 2
    498 Workers Launched: 2
    499343->  Parallel Seq Scan on review r
    500344Filter: (customer_id = 100)
     
    540384{{{
    541385GroupAggregate  (cost=73811.09..73811.84 rows=25 width=117) (actual time=122.594..123.137 rows=1 loops=1)
    542 Group Key: u.user_id
    543 ->  Sort  (cost=73811.09..73811.15 rows=25 width=77) (actual time=122.573..123.117 rows=49 loops=1)
    544 Sort Key: u.user_id, a.appointment_id
    545 Sort Method: quicksort  Memory: 29kB
    546 ->  Nested Loop Left Join  (cost=1001.28..73810.51 rows=25 width=77) (actual time=3.738..123.089 rows=49 loops=1)
    547 ->  Nested Loop Left Join  (cost=1000.85..73785.99 rows=5 width=69) (actual time=3.437..122.737 rows=7 loops=1)
    548 ->  Nested Loop  (cost=0.85..16.89 rows=1 width=53) (actual time=1.866..1.868 rows=1 loops=1)
    549 ->  Index Scan using pk_customer on customer c
    550 Index Cond: (customer_id = 100)
    551 ->  Index Scan using pk_user on "user" u
    552 Index Cond: (user_id = c.user_id)
    553 ->  Gather
    554 Workers Planned: 2
    555 Workers Launched: 2
    556386->  Parallel Seq Scan on appointment a
    557387Filter: (customer_id = 100)
    558388Rows Removed by Filter: 1666665
    559 ->  Materialize
    560389->  Index Scan using idx_review_customer_profile on review r
    561390Index Cond: (customer_id = 100)
     
    582411}}}
    583412
    584 Затоа времето се подобрува значително, но не паѓа под 1 ms како кај некои други погледи. За дополнителна оптимизација може да се разгледа и индекс на `appointment(customer_id)`, особено ако профилот секогаш ги прикажува резервациите на конкретниот корисник.
     413Затоа времето се подобрува значително, но не паѓа под 1 ms како кај некои други погледи.
    585414
    586415=== Споредба на времиња ===
     
    605434}}}
    606435
    607 За точно мерење на времето пред и после оптимизација, прво ги бришеме индексите доколку постојат, потоа го извршуваме прашалникот без индекси, па ги креираме индексите и повторно го извршуваме истиот прашалник.
    608 
    609 {{{
    610 -- 1. Бришење на индексите ако постојат
    611 DROP INDEX IF EXISTS idx_reschedule_request_status;
    612 DROP INDEX IF EXISTS idx_reschedule_request_old_slot_id;
    613 DROP INDEX IF EXISTS idx_reschedule_request_new_slot_id;
    614 
    615 -- 2. Освежување на статистиките
    616 ANALYZE reschedule_request;
    617 
     436За оптимизација го тестираме истиот прашалник пред и после додавање на индексите.
     437
     438{{{
    618439-- 3. Мерење без индекси
    619440EXPLAIN ANALYZE
     
    631452CREATE INDEX IF NOT EXISTS idx_reschedule_request_new_slot_id
    632453ON reschedule_request(new_slot_id);
    633 
    634 -- 5. Освежување на статистиките
    635 ANALYZE reschedule_request;
    636 
    637 -- 6. Мерење со индекси
    638 EXPLAIN ANALYZE
    639 SELECT *
    640 FROM reschedule_overview
    641 WHERE status = 'pending';
    642454}}}
    643455
     
    650462{{{
    651463Merge Join  (cost=124.66..141.39 rows=667 width=64) (actual time=4.200..5.002 rows=667 loops=1)
    652 Merge Cond: (ts_new.slot_id = rr.new_slot_id)
    653 ->  Index Scan using pk_time_slot on time_slot ts_new
    654 ->  Sort  (cost=124.22..125.89 rows=667 width=56) (actual time=2.050..2.087 rows=667 loops=1)
    655 Sort Key: rr.new_slot_id
    656 Sort Method: quicksort  Memory: 82kB
    657 ->  Merge Join  (cost=82.41..92.93 rows=667 width=56) (actual time=0.611..1.932 rows=667 loops=1)
    658 Merge Cond: (ts_old.slot_id = rr.old_slot_id)
    659 ->  Index Scan using pk_time_slot on time_slot ts_old
    660 ->  Sort  (cost=81.31..82.98 rows=667 width=48) (actual time=0.575..0.605 rows=667 loops=1)
    661 Sort Key: rr.old_slot_id
    662 Sort Method: quicksort  Memory: 77kB
    663464->  Seq Scan on reschedule_request rr
    664465Filter: ((status)::text = 'pending'::text)
     
    677478}}}
    678479
    679 Ова значи дека базата ја чита табелата `reschedule_request`, па потоа ги задржува само барањата со статус `pending`. Иако табелата во овој тест не е многу голема, ова може да стане проблем ако бројот на барања за презакажување се зголеми.
     480Ова значи дека базата ја чита табелата `reschedule_request`, па потоа ги задржува само барањата со статус `pending`.
    680481
    681482За оптимизација ги креираме следните индекси:
     
    702503{{{
    703504Merge Join  (cost=121.42..138.15 rows=667 width=64) (actual time=3.341..3.903 rows=667 loops=1)
    704 Merge Cond: (ts_new.slot_id = rr.new_slot_id)
    705 ->  Index Scan using pk_time_slot on time_slot ts_new
    706 ->  Sort  (cost=120.98..122.65 rows=667 width=56) (actual time=1.460..1.490 rows=667 loops=1)
    707 Sort Key: rr.new_slot_id
    708 Sort Method: quicksort  Memory: 82kB
    709 ->  Merge Join  (cost=79.17..89.69 rows=667 width=56) (actual time=0.712..1.359 rows=667 loops=1)
    710 Merge Cond: (ts_old.slot_id = rr.old_slot_id)
    711 ->  Index Scan using pk_time_slot on time_slot ts_old
    712 ->  Sort  (cost=78.07..79.74 rows=667 width=48) (actual time=0.691..0.718 rows=667 loops=1)
    713 Sort Key: rr.old_slot_id
    714 Sort Method: quicksort  Memory: 77kB
    715505->  Bitmap Heap Scan on reschedule_request rr
    716506Recheck Cond: ((status)::text = 'pending'::text)
    717 Heap Blocks: exact=25
    718507->  Bitmap Index Scan on idx_reschedule_request_status
    719508Index Cond: ((status)::text = 'pending'::text)
     
    730519}}}
    731520
    732 и потоа:
    733 
    734 {{{
    735 Bitmap Heap Scan on reschedule_request rr
    736 Recheck Cond: ((status)::text = 'pending'::text)
    737 }}}
    738 
    739521Ова значи дека базата преку индексот прво ги наоѓа барањата кои имаат статус `pending`, а потоа ги чита само тие редици од табелата.
    740522
     
    753535
    754536Со додавање на соодветни индекси успеавме да ги подобриме перформансите на тестираните прашалници во системот Rezervo.
    755 
    756 Најголеми подобрувања се забележуваат кај:
    757537
    758538||= Поглед =||= Пред индекс =||= После индекс =||= Подобрување =||
     
    767547Кај `customer_appointments_view` подобрувањето е исто така значајно, бидејќи парцијалниот индекс ги содржи само резервациите кои не се откажани. Со тоа се избегнува дополнително филтрирање според статус.
    768548
    769 Кај `customer_profile_view` подобрувањето е значително, бидејќи индексот `idx_review_customer_profile` го заменува секвенцијалното скенирање на табелата `review` со директно индексно пребарување според `customer_id`. Сепак, бидејќи табелата `appointment` и понатаму се скенира секвенцијално, прашалникот не се намалува под 1 ms.
    770 
    771 Кај `review_details` подобрувањето е помало. Причината е тоа што условот `rating = 5` враќа многу голем број редици. Индексот го заменува целосното секвенцијално скенирање со `Bitmap Index Scan`, но бидејќи сепак мора да се прочитаат околу 1 милион рецензии, разликата не е толку голема.
     549Кај `customer_profile_view` подобрувањето е значително, бидејќи индексот `idx_review_customer_profile` го заменува секвенцијалното скенирање на табелата `review` со директно индексно пребарување според `customer_id`. Иако табелата `appointment` и понатаму се скенира секвенцијално, вкупното време се намалува од **546.242 ms** на **123.200 ms**.
     550
     551Кај `review_details` подобрувањето е помало, бидејќи условот `rating = 5` враќа многу голем број редици. Индексот го заменува целосното секвенцијално скенирање со `Bitmap Index Scan`, но бидејќи сепак мора да се прочитаат околу 1 милион рецензии, разликата не е толку голема.
    772552
    773553Кај `reschedule_overview` подобрувањето е најмало, бидејќи табелата `reschedule_request` во тестот има релативно мал број редици. Индексот `idx_reschedule_request_status` се користи во планот, но разликата меѓу времето пред и после индексот е мала.
    774554
    775 == 7. Влијание на индексите и можност за бришење на некои индекси ==
     555== 7. Одлука кои индекси се задржуваат, а кои се бришат ==
    776556
    777557Индексите го подобруваат читањето на податоците, но имаат и цена. При секој `INSERT`, `UPDATE` или `DELETE`, базата мора да ги ажурира и индексите. Затоа не е секогаш оправдано да се задржи индекс кој дава многу мало подобрување.
    778558
    779 Во нашите тестови, индексите кои даваат најголема добивка и се оправдани за задржување се:
    780 
    781 {{{
     559Според добиените резултати, ги задржуваме индексите кои имаат значително намалување на времето и се користат во чести сценарија во апликацијата:
     560
     561{{{
     562-- Индекси кои ги задржуваме
     563
    782564idx_appointment_customer_not_cancelled
    783565idx_time_slot_available_business_date
     
    785567}}}
    786568
    787 Овие индекси значително го намалуваат времето на извршување и директно одговараат на чести сценарија во апликацијата: преглед на резервации, пребарување достапни термини и приказ на кориснички профил.
    788 
    789 Од друга страна, кај следните индекси добивката е помала:
    790 
    791 {{{
    792 idx_review_rating_details
    793 idx_reschedule_request_status
    794 idx_reschedule_request_old_slot_id
    795 idx_reschedule_request_new_slot_id
    796 }}}
    797 
    798 Индексот `idx_review_rating_details` го намалува времето од **360.970 ms** на **239.802 ms**, но бидејќи `rating = 5` враќа многу голем број редици, подобрувањето е ограничено. Доколку филтрирањето по оценка не е често сценарио во апликацијата, може да се размисли овој индекс да се избрише.
    799 
    800 Индексот `idx_reschedule_request_status` го намалува времето од **5.051 ms** на **3.988 ms**, што е мала разлика. Дополнително, индексите `idx_reschedule_request_old_slot_id` и `idx_reschedule_request_new_slot_id` не се директно искористени во прикажаниот план на извршување. Затоа, ако овие индекси не се користат во други прашалници, може да се размисли за нивно бришење.
    801 
    802 Бришењето би се направило со:
    803 
    804 {{{
     569Овие индекси се оправдани затоа што носат значајно подобрување:
     570
     571||= Индекс =||= Поглед =||= Причина за задржување =||
     572|| idx_appointment_customer_not_cancelled || customer_appointments_view || времето се намалува од 7.802 ms на 0.803 ms ||
     573|| idx_time_slot_available_business_date || available_slots || времето се намалува од 7157.628 ms на 0.580 ms ||
     574|| idx_review_customer_profile || customer_profile_view || времето се намалува од 546.242 ms на 123.200 ms ||
     575
     576Од друга страна, индексите кај кои подобрувањето е мало ги бришеме, освен ако не се користат во други прашалници надвор од оваа анализа.
     577
     578{{{
     579-- Индекси кои ги бришеме
     580
    805581DROP INDEX IF EXISTS idx_review_rating_details;
    806582
     
    810586}}}
    811587
    812 Заклучуваме дека индексите треба да се задржат само ако носат значајно подобрување или ако се користат често во апликацијата. Во спротивно, подобро е да се избришат за да не создаваат непотребен трошок при внесување и ажурирање на податоците.
    813 
    814 Конечно, најоправдани индекси за задржување во оваа фаза се парцијалните индекси за `customer_appointments_view` и `available_slots`, како и индексот за `customer_profile_view`, бидејќи таму добивката е најголема и сценаријата се чести во реалната употреба на системот.
     588Индексот `idx_review_rating_details` го намалува времето од **360.970 ms** на **239.802 ms**, што е подобрување, но не е доволно големо во споредба со бројот на редици кои сепак мора да се прочитаат. Бидејќи `rating = 5` враќа околу 1 милион редици, индексот има ограничен ефект.
     589
     590Индексот `idx_reschedule_request_status` го намалува времето од **5.051 ms** на **3.988 ms**, што е многу мала разлика. Дополнително, индексите `idx_reschedule_request_old_slot_id` и `idx_reschedule_request_new_slot_id` не се директно искористени во прикажаниот план на извршување. Затоа тие индекси ги бришеме за да не создаваат непотребен трошок при внесување и ажурирање на податоци.
     591
     592Заклучуваме дека најоправдани индекси за задржување во оваа фаза се парцијалните индекси за `customer_appointments_view` и `available_slots`, како и индексот за `customer_profile_view`, бидејќи таму добивката е најголема и сценаријата се чести во реалната употреба на системот.