Changes between Version 9 and Version 10 of Optimization
- Timestamp:
- 06/14/26 21:23:31 (6 days ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Optimization
v9 v10 5 5 Rezervo е систем за резервации кај занаетчии и даватели на услуги, каде што корисниците можат да пребаруваат достапни термини, да закажуваат, менуваат или откажуваат резервации, како и да оставаат рецензии за услугите. 6 6 7 За мерење на времињата се користи `EXPLAIN ANALYZE`. Кај секој поглед прво се брише индексот доколку постои, потоа се мери времето без индекс, па се креира индексот и повторно се мери времето со индекс. Како резултат во документацијата се зема вредноста `Execution Time`.7 За мерење на времињата се користи `EXPLAIN ANALYZE`. Кај секој поглед прво се мери времето без индекс, потоа се креира индексот и повторно се мери времето со индекс. Како резултат во документацијата се зема вредноста `Execution Time`. 8 8 9 9 == 1. Анализа на поглед customer_appointments_view, преглед на резервации за конкретен корисник == … … 19 19 }}} 20 20 21 За точно да го измериме времето пред и после оптимизација, прво го бришеме индексот ако веќе постои, потоа го извршуваме прашалникот без индекс, па го креираме индексот и повторно го извршуваме истиот прашалник. 22 23 {{{ 24 25 -- 1. Мерење без индекс 21 За оптимизација го тестираме истиот прашалник пред и после додавање на индексот. 22 23 {{{ 24 -- 3. Мерење без индекс 26 25 EXPLAIN ANALYZE 27 26 SELECT * … … 29 28 WHERE customer_id = 100; 30 29 31 -- 2. Креирање на индекс30 -- 4. Креирање на индекс 32 31 CREATE INDEX IF NOT EXISTS idx_appointment_customer_not_cancelled 33 32 ON appointment(customer_id) … … 45 44 -> Hash Join (cost=87.68..126.58 rows=5 width=97) (actual time=3.625..4.537 rows=6 loops=1) 46 45 Hash 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 c49 Index Cond: (customer_id = 100)50 -> Hash Join51 Hash Cond: (e.employee_id = a.employee_id)52 -> Seq Scan on employee e53 -> Hash54 -> Hash Right Join55 -> Seq Scan on business_location bl56 -> Hash57 -> Hash Join58 -> Seq Scan on business b59 -> Hash60 46 -> Index Scan using idx_appointment_customer_profile on appointment a 61 47 Index Cond: (customer_id = 100) 62 48 Filter: ((status)::text <> 'cancelled'::text) 63 49 Rows Removed by Filter: 1 64 -> Index Scan using pk_time_slot on time_slot ts65 Index Cond: (slot_id = a.slot_id)66 50 67 51 Planning Time: 8.862 ms … … 69 53 }}} 70 54 71 Во овој план се гледа дека за табелата `appointment` се користи индекс от `idx_appointment_customer_profile`, но сепак дополнително се применува филтерот:55 Во овој план се гледа дека за табелата `appointment` се користи индекс според `customer_id`, но сепак дополнително се применува филтерот: 72 56 73 57 {{{ … … 95 79 {{{ 96 80 Nested 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 c99 Index Cond: (customer_id = 100)100 -> Hash Join101 Hash Cond: (e.employee_id = a.employee_id)102 -> Seq Scan on employee e103 -> Hash104 -> Hash Right Join105 -> Seq Scan on business_location bl106 -> Hash107 -> Hash Join108 -> Seq Scan on business b109 -> Hash110 -> Hash Join111 Hash Cond: (s.service_id = a.service_id)112 -> Seq Scan on service s113 -> Hash114 81 -> Index Scan using idx_appointment_customer_not_cancelled on appointment a 115 82 Index Cond: (customer_id = 100) 116 -> Index Scan using pk_time_slot on time_slot ts117 Index Cond: (slot_id = a.slot_id)118 83 119 84 Planning Time: 3.150 ms … … 150 115 }}} 151 116 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 {{{ 161 120 -- 3. Мерење без индекс 162 121 EXPLAIN ANALYZE … … 170 129 ON time_slot(business_id, date) 171 130 WHERE is_available = TRUE; 172 173 -- 5. Освежување на статистиките174 ANALYZE time_slot;175 176 -- 6. Мерење со индекс177 EXPLAIN ANALYZE178 SELECT *179 FROM available_slots180 WHERE business_id = 1181 AND date = CURRENT_DATE;182 131 }}} 183 132 … … 190 139 {{{ 191 140 Nested 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 Loop195 -> Nested Loop196 -> Nested Loop197 -> Index Scan using uq_business_service_business_service on business_service bs198 Index Cond: (business_id = 1)199 Filter: is_active200 -> Materialize201 -> Index Scan using pk_business on business b202 Index Cond: (business_id = 1)203 -> Materialize204 141 -> Gather 205 142 Workers Planned: 2 … … 208 145 Filter: (is_available AND (business_id = 1) AND (date = CURRENT_DATE)) 209 146 Rows Removed by Filter: 6666651 210 -> Memoize211 Cache Key: ts.employee_id212 -> Index Scan using pk_employee on employee e213 Index Cond: (employee_id = ts.employee_id)214 -> Index Only Scan using uq_employee_service_employee_service on employee_service es215 Index Cond: (employee_id = e.employee_id)216 Heap Fetches: 0217 -> Index Scan using pk_service on service s218 Index Cond: (service_id = es.service_id)219 147 220 148 Planning Time: 4.741 ms … … 250 178 {{{ 251 179 Nested 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 b254 Index Cond: (business_id = 1)255 -> Hash Join256 Hash Cond: (es.service_id = bs.service_id)257 -> Nested Loop258 Join Filter: (es.employee_id = ts.employee_id)259 -> Hash Join260 Hash Cond: (ts.employee_id = e.employee_id)261 180 -> Index Scan using idx_time_slot_available_business_date on time_slot ts 262 181 Index Cond: ((business_id = 1) AND (date = CURRENT_DATE)) 263 -> Hash264 -> Seq Scan on employee e265 -> Index Only Scan using uq_employee_service_employee_service on employee_service es266 Index Cond: (employee_id = e.employee_id)267 Heap Fetches: 0268 -> Hash269 -> Bitmap Heap Scan on business_service bs270 Recheck Cond: (business_id = 1)271 Filter: is_active272 -> Bitmap Index Scan on uq_business_service_business_service273 Index Cond: (business_id = 1)274 -> Index Scan using pk_service on service s275 Index Cond: (service_id = es.service_id)276 182 277 183 Planning Time: 2.741 ms … … 307 213 }}} 308 214 309 За точно мерење на времето пред и после оптимизација, прво го бришеме индексот доколку постои, потоа го извршуваме прашалникот без индекс, па го креираме индексот и повторно го извршуваме истиот прашалник. 310 311 {{{ 312 -- 1. Бришење на индексот ако веќе постои 313 DROP INDEX IF EXISTS idx_review_rating_details; 314 315 -- 2. Освежување на статистиките 316 ANALYZE review; 317 215 За оптимизација го тестираме истиот прашалник пред и после додавање на индексот. 216 217 {{{ 318 218 -- 3. Мерење без индекс 319 219 EXPLAIN ANALYZE … … 325 225 CREATE INDEX IF NOT EXISTS idx_review_rating_details 326 226 ON review(rating); 327 328 -- 5. Освежување на статистиките329 ANALYZE review;330 331 -- 6. Мерење со индекс332 EXPLAIN ANALYZE333 SELECT *334 FROM review_details335 WHERE rating = 5;336 227 }}} 337 228 … … 344 235 {{{ 345 236 Hash 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)347 237 -> Seq Scan on review r (cost=0.00..109231.71 rows=1006495 width=27) (actual time=0.169..259.457 rows=1000001 loops=1) 348 238 Filter: (rating = 5) 349 239 Rows 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: 59kB352 -> Seq Scan on business b (cost=0.00..27.01 rows=1001 width=16) (actual time=0.020..0.311 rows=1001 loops=1)353 240 354 241 Planning Time: 2.849 ms … … 383 270 {{{ 384 271 Hash 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 387 273 Recheck 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 390 275 Index 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: 59kB393 -> Seq Scan on business b (cost=0.00..27.01 rows=1001 width=16) (actual time=0.005..0.113 rows=1001 loops=1)394 276 395 277 Planning Time: 0.593 ms … … 434 316 }}} 435 317 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 {{{ 449 321 -- 3. Мерење без индекс 450 322 EXPLAIN ANALYZE … … 456 328 CREATE INDEX IF NOT EXISTS idx_review_customer_profile 457 329 ON review(customer_id, rating); 458 459 -- 5. Освежување на статистиките460 ANALYZE appointment;461 ANALYZE review;462 463 -- 6. Мерење со индекс464 EXPLAIN ANALYZE465 SELECT *466 FROM customer_profile_view467 WHERE customer_id = 100;468 330 }}} 469 331 … … 476 338 {{{ 477 339 GroupAggregate (cost=147561.37..147562.12 rows=25 width=117) (actual time=545.746..546.153 rows=1 loops=1) 478 Group Key: u.user_id479 -> 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_id481 Sort Method: quicksort Memory: 29kB482 -> 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 c486 Index Cond: (customer_id = 100)487 -> Index Scan using pk_user on "user" u488 Index Cond: (user_id = c.user_id)489 -> Gather490 Workers Planned: 2491 Workers Launched: 2492 340 -> Parallel Seq Scan on appointment a 493 341 Filter: (customer_id = 100) 494 342 Rows Removed by Filter: 1666665 495 -> Materialize496 -> Gather497 Workers Planned: 2498 Workers Launched: 2499 343 -> Parallel Seq Scan on review r 500 344 Filter: (customer_id = 100) … … 540 384 {{{ 541 385 GroupAggregate (cost=73811.09..73811.84 rows=25 width=117) (actual time=122.594..123.137 rows=1 loops=1) 542 Group Key: u.user_id543 -> 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_id545 Sort Method: quicksort Memory: 29kB546 -> 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 c550 Index Cond: (customer_id = 100)551 -> Index Scan using pk_user on "user" u552 Index Cond: (user_id = c.user_id)553 -> Gather554 Workers Planned: 2555 Workers Launched: 2556 386 -> Parallel Seq Scan on appointment a 557 387 Filter: (customer_id = 100) 558 388 Rows Removed by Filter: 1666665 559 -> Materialize560 389 -> Index Scan using idx_review_customer_profile on review r 561 390 Index Cond: (customer_id = 100) … … 582 411 }}} 583 412 584 Затоа времето се подобрува значително, но не паѓа под 1 ms како кај некои други погледи. За дополнителна оптимизација може да се разгледа и индекс на `appointment(customer_id)`, особено ако профилот секогаш ги прикажува резервациите на конкретниот корисник.413 Затоа времето се подобрува значително, но не паѓа под 1 ms како кај некои други погледи. 585 414 586 415 === Споредба на времиња === … … 605 434 }}} 606 435 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 {{{ 618 439 -- 3. Мерење без индекси 619 440 EXPLAIN ANALYZE … … 631 452 CREATE INDEX IF NOT EXISTS idx_reschedule_request_new_slot_id 632 453 ON reschedule_request(new_slot_id); 633 634 -- 5. Освежување на статистиките635 ANALYZE reschedule_request;636 637 -- 6. Мерење со индекси638 EXPLAIN ANALYZE639 SELECT *640 FROM reschedule_overview641 WHERE status = 'pending';642 454 }}} 643 455 … … 650 462 {{{ 651 463 Merge 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_new654 -> 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_id656 Sort Method: quicksort Memory: 82kB657 -> 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_old660 -> 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_id662 Sort Method: quicksort Memory: 77kB663 464 -> Seq Scan on reschedule_request rr 664 465 Filter: ((status)::text = 'pending'::text) … … 677 478 }}} 678 479 679 Ова значи дека базата ја чита табелата `reschedule_request`, па потоа ги задржува само барањата со статус `pending`. Иако табелата во овој тест не е многу голема, ова може да стане проблем ако бројот на барања за презакажување се зголеми.480 Ова значи дека базата ја чита табелата `reschedule_request`, па потоа ги задржува само барањата со статус `pending`. 680 481 681 482 За оптимизација ги креираме следните индекси: … … 702 503 {{{ 703 504 Merge 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_new706 -> 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_id708 Sort Method: quicksort Memory: 82kB709 -> 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_old712 -> 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_id714 Sort Method: quicksort Memory: 77kB715 505 -> Bitmap Heap Scan on reschedule_request rr 716 506 Recheck Cond: ((status)::text = 'pending'::text) 717 Heap Blocks: exact=25718 507 -> Bitmap Index Scan on idx_reschedule_request_status 719 508 Index Cond: ((status)::text = 'pending'::text) … … 730 519 }}} 731 520 732 и потоа:733 734 {{{735 Bitmap Heap Scan on reschedule_request rr736 Recheck Cond: ((status)::text = 'pending'::text)737 }}}738 739 521 Ова значи дека базата преку индексот прво ги наоѓа барањата кои имаат статус `pending`, а потоа ги чита само тие редици од табелата. 740 522 … … 753 535 754 536 Со додавање на соодветни индекси успеавме да ги подобриме перформансите на тестираните прашалници во системот Rezervo. 755 756 Најголеми подобрувања се забележуваат кај:757 537 758 538 ||= Поглед =||= Пред индекс =||= После индекс =||= Подобрување =|| … … 767 547 Кај `customer_appointments_view` подобрувањето е исто така значајно, бидејќи парцијалниот индекс ги содржи само резервациите кои не се откажани. Со тоа се избегнува дополнително филтрирање според статус. 768 548 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 милион рецензии, разликата не е толку голема. 772 552 773 553 Кај `reschedule_overview` подобрувањето е најмало, бидејќи табелата `reschedule_request` во тестот има релативно мал број редици. Индексот `idx_reschedule_request_status` се користи во планот, но разликата меѓу времето пред и после индексот е мала. 774 554 775 == 7. Влијание на индексите и можност за бришење на некои индекси==555 == 7. Одлука кои индекси се задржуваат, а кои се бришат == 776 556 777 557 Индексите го подобруваат читањето на податоците, но имаат и цена. При секој `INSERT`, `UPDATE` или `DELETE`, базата мора да ги ажурира и индексите. Затоа не е секогаш оправдано да се задржи индекс кој дава многу мало подобрување. 778 558 779 Во нашите тестови, индексите кои даваат најголема добивка и се оправдани за задржување се: 780 781 {{{ 559 Според добиените резултати, ги задржуваме индексите кои имаат значително намалување на времето и се користат во чести сценарија во апликацијата: 560 561 {{{ 562 -- Индекси кои ги задржуваме 563 782 564 idx_appointment_customer_not_cancelled 783 565 idx_time_slot_available_business_date … … 785 567 }}} 786 568 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 805 581 DROP INDEX IF EXISTS idx_review_rating_details; 806 582 … … 810 586 }}} 811 587 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`, бидејќи таму добивката е најголема и сценаријата се чести во реалната употреба на системот.
