Changes between Version 87 and Version 88 of QueryOptimization


Ignore:
Timestamp:
06/30/26 23:09:12 (5 days ago)
Author:
231027
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • QueryOptimization

    v87 v88  
    2020==== 1. Примарен филтер:
    2121
    22 Примарен филтер за овој поглед е `venue_id` (ID на објектот), бидејќи најчестото пребарување е насочено кон визуелизација или вчитување на комплетната мапа на седишта за еден конкретен објект кога се купува билет.
     22Примарен филтер за овој поглед е `venue_id` (ID на објектот), бидејќи најчестото пребарување во апликацијата е насочено кон визуелизација или вчитување на комплетната мапа на седишта за еден конкретен објект кога корисникот сака да купи билет.
    2323
    2424==== 2. Случај на употреба:
    2525
    26 Погледот се користи при интерактивниот приказ на салата/стадионот во корисничкиот интерфејс. Кога купувачот ќе избере настан, апликацијата мора веднаш да го исцрта распоредот на седишта по секции и редови за тој објект. Перформансите тука директно влијаат врз брзината на вчитување на корисничката страница за избор на седиште.
     26Погледот се користи при интерактивниот приказ на салата или стадионот во корисничкиот интерфејс. Кога купувачот ќе избере одреден настан, апликацијата мора веднаш да го исцрта распоредот на седишта по секции и редови за тој објект. Перформансите тука директно влијаат врз „time-to-interactive“ метриката на корисничката страница за избор на место.
    2727
    2828==== 3. Иницијално време:
    2929
    30  * '''SELECT:''' 2.190 ms
    31  * '''INSERT:''' 4.752 ms
    32  * '''UPDATE:''' 0.133 ms
     30 * '''SELECT:''' 2.190 ms (Времето е мерено во продукциска околина пред оптимизација).
     31 * '''INSERT:''' 4.752 ms (Време потребно за запишување на нов ред во табелата `Seat` заедно со проверка на сите интегритетни констреинти).
     32 * '''UPDATE:''' 0.133 ms (Инстантна операција базирана на примарен клуч).
    3333
    3434==== 4. Анализа на планот на извршување (без индекси):
    3535
    36 При '''SELECT''' операцијата, '''PostgreSQL''' паметно ги користи веќе постоечките уникатни индекси генерирани од бизнис констреинтите, овозможувајќи брз '''Index Scan'''. Планерот успешно ги мапира релациите без потреба од дополнителни оптимизации.
     36При '''SELECT''' операцијата, '''PostgreSQL''' паметно ги користи веќе постоечките уникатни индекси генерирани од бизнис констреинтите (`uq_section_venue_name` на `Section` и `uq_seat_section_number` на `Seat`). Планерот користи '''Nested Loop''' операција за спојување на табелите: прво го наоѓа објектот по ID, потоа преку `venue_id` ги лоцира сите секции, и на крај за секоја секција извршува '''Index Scan''' за да ги повлече соодветните седишта. Оваа патека овозможува брз пристап без потреба од скапи секвенцијални скенирања.
    3737
    3838 * '''SELECT'''
     
    108108==== 5. Оптимизација и индексирање:
    109109
    110 Бидејќи постоечките уникатни констреинти веќе идеално ги покриваат '''JOIN''' релациите, креирањето на дополнителни индекси е непотребно и би довело до залудно трошење на мемориски ресурси. Погледот е веќе оптимизиран. Доволно е само да се изврши:
     110Бидејќи постоечките уникатни констреинти веќе идеално ги покриваат '''JOIN''' релациите, креирањето на дополнителни индекси е непотребно и би довело до залудно трошење на мемориски ресурси и забавување на запишувањето ('''INSERT'''/'''UPDATE'''). Погледот е оценет како оптимален во својата тековна форма. Доволно е само да се изврши:
    111111
    112112{{{
     
    126126== Анализа и оптимизација на `User_Tickets`
    127127
    128 Овој поглед дава детален хронолошки преглед на сите купени поединечни билети по корисник, вклучувајќи ја точната платена цена, QR-кодот за влез и терминот на настанот. Преку релацијата со ставките за рефундација, погледот нуди и инстантна информација за тоа кои карти се откажани и кога се вратени парите.
     128Овој поглед обезбедува сеопфатен хронолошки приказ на сите трансакции по корисник. Покрај основните информации како настан, цена и QR-код, погледот инкорпорира податоци за рефундации (преку '''LEFT JOIN''' со табелите за рефундација), овозможувајќи моментна идентификација на статусот на секој билет. Погледот е филтриран само за активни корисници, со што се елиминираат податоците од неактивни профили.
    129129
    130130{{{
    131131
    132132CREATE OR REPLACE VIEW "User_Tickets" AS
    133 SELECT u.user_id,
    134        u.username,
    135        toi.order_item_id,
    136        t.ticket_id,
    137        e.event_id,
    138        e.name AS event_name,
    139        eh.event_time,
    140        toi.qr_code,
    141        toi.item_price AS price_paid,
    142        tri.refund_item_id,
    143        tr.refund_time
     133SELECT u.user_id, u.username, toi.order_item_id, t.ticket_id, e.event_id, e.name AS event_name, eh.event_time,
     134       toi.qr_code, toi.item_price AS price_paid, tri.refund_item_id, tr.refund_time
    144135FROM "User" u
    145 JOIN "Regular_User" ru ON u.user_id = ru.user_id
    146 JOIN "Ticket_Order" o ON ru.user_id = o.user_id
    147 JOIN "Ticket_Order_Item" toi ON o.order_id = toi.order_id
    148 JOIN "Ticket" t ON toi.ticket_id = t.ticket_id
    149 JOIN "Event_Happening" eh ON t.event_happening_id = eh.event_happening_id
    150 JOIN "Event" e ON eh.event_id = e.event_id
    151 LEFT JOIN "Ticket_Refund_Item" tri ON toi.order_item_id = tri.order_item_id
    152 LEFT JOIN "Ticket_Refund" tr ON tri.refund_id = tr.refund_id;
    153 
    154 }}}
    155 
    156 Погледот е веќе најоптимално напишан и не треба да се преуредува.
     136    JOIN "Regular_User" ru ON u.user_id = ru.user_id
     137    JOIN "Ticket_Order" o ON ru.user_id = o.user_id
     138    JOIN "Ticket_Order_Item" toi ON o.order_id = toi.order_id
     139    JOIN "Ticket" t ON toi.ticket_id = t.ticket_id
     140    JOIN "Event_Happening" eh ON t.event_happening_id = eh.event_happening_id
     141    JOIN "Event" e ON eh.event_id = e.event_id
     142    LEFT JOIN "Ticket_Refund_Item" tri ON toi.order_item_id = tri.order_item_id
     143    LEFT JOIN "Ticket_Refund" tr ON tri.refund_id = tr.refund_id
     144WHERE u.is_active = TRUE;
     145
     146}}}
     147
     148Погледот е веќе најоптимално напишан со користење на постоечките уникатни констреинти и не бара дополнителни модификации.
    157149
    158150==== 1. Примарен филтер:
    159151
    160 Примарен филтер за овој поглед е `user_id` (ID на корисникот), бидејќи најчестото и критично пребарување е кога најавениот клиент ја отвора својата корисничка профилна страница за да ги види своите активни или минати билети.
     152Примарен филтер за овој поглед е `user_id` (ID на корисникот), бидејќи најчестото и критично пребарување е кога најавениот клиент ја отвора својата корисничка профилна страница („My Tickets“) за да ги види своите активни или минати билети.
    161153
    162154==== 2. Случај на употреба:
    163155
    164 Погледот претставува јадро на апликацијата во делот за дигитални билети (My Tickets). Секојпат кога корисникот сака да го прикаже својот QR-код на билетот за некој настан, системот го извршува овој прашалник. Доцнење на овој одзив предизвикува лошо корисничко искуство и застој на влезните капии.
     156Погледот претставува јадро на апликацијата во делот за дигитални билети. Секојпат кога корисникот сака да го прикаже својот QR-код на билетот за некој настан, системот го извршува овој прашалник. Доцнење на овој одзив предизвикува лошо корисничко искуство и застој на влезните капии при проверка на билетите.
    165157
    166158==== 3. Иницијално време:
    167159
    168  * '''SELECT:''' 676.751 ms (Исклучително бавно поради комплексноста од 9 поврзани табели и секвенцијално скенирање на огромната табела за билети).
    169  * '''INSERT:''' 18.187 ms (Бавно извршување поради диск операции при евалуација на констреинтите).
    170  * '''UPDATE:''' 0.071 ms (Инстантна брзина благодарение на примарниот клуч).
     160 * '''SELECT:''' 375.993 ms (Исклучително бавно поради комплексноста од поврзување на 9 табели и секвенцијално скенирање).
     161 * '''INSERT:''' 0.523 ms
     162 * '''UPDATE:''' 0.118 ms
    171163
    172164==== 4. Анализа на планот на извршување (без индекси):
    173165
    174 При селекција без индекси, базата е принудена да користи '''Gather''' операција со два дополнителни паралелни работници ('''Workers Planned: 2'''). Најголемиот проблем се јавува во тоа што се врши секвенцијално скенирање со проверка на релациите низ хард дискот, што генерира огромни 38,603 диск читања ('''shared read=38603'''). Кај '''INSERT''' операцијата, дури 17.637 ms се губат во тригерите за проверка на '''foreign key''' констреинтите бидејќи базата нема брза индексна патека до поврзаните записи.
     166Со воведувањето на новите '''B-tree''' индекси, планерот го напушти паралелното секвенцијално скенирање и премина кон '''Nested Loop''' операција. Ова овозможува базата да ја најде нарачката на корисникот преку `idx_ticket_order_user_id` во само еден чекор, а потоа со преостанатите индекси директно да ги „отвори“ ставките на нарачката (`Ticket_Order_Item`) и билетите (`Ticket`), избегнувајќи пребарување низ целиот диск.
    175167
    176168 * '''SELECT'''
     
    179171
    180172EXPLAIN ANALYZE
    181 SELECT * FROM "User_Tickets"
     173SELECT *
     174FROM "User_Tickets"
    182175WHERE user_id = 5;
    183176
     
    185178
    186179||= QUERY PLAN =||
    187 ||Gather  (cost\=66949.49..416072.10 rows\=4 width\=145) (actual time\=667.628..676.676 rows\=0.00 loops\=1)||
    188 ||  Workers Planned: 2||
    189 ||  Workers Launched: 2||
    190 ||  Buffers: shared read\=38603||
    191 ||  ->  Nested Loop Left Join  (cost\=65949.49..415071.70 rows\=2 width\=145) (actual time\=612.744..612.748 rows\=0.00 loops\=3)||
    192 ||        Buffers: shared read\=38603||
    193 ||        ->  Nested Loop Left Join  (cost\=65949.07..415070.67 rows\=2 width\=145) (actual time\=612.743..612.747 rows\=0.00 loops\=3)||
    194 ||              Buffers: shared read\=38603||
    195 ||              ->  Nested Loop  (cost\=65948.64..415069.63 rows\=2 width\=129) (actual time\=612.742..612.746 rows\=0.00 loops\=3)||
    196 ||                    Buffers: shared read\=38603||
    197 ||                    ->  Nested Loop  (cost\=65948.35..415068.90 rows\=2 width\=98) (actual time\=612.742..612.745 rows\=0.00 loops\=3)||
    198 ||                          Buffers: shared read\=38603||
    199 ||                          ->  Nested Loop  (cost\=65948.07..415068.27 rows\=2 width\=90) (actual time\=612.741..612.745 rows\=0.00 loops\=3)||
    200 ||                                Buffers: shared read\=38603||
    201 ||                                ->  Nested Loop  (cost\=65947.63..415065.48 rows\=2 width\=82) (actual time\=612.741..612.744 rows\=0.00 loops\=3)||
    202 ||                                      Buffers: shared read\=38603||
    203 ||                                      ->  Parallel Hash Join  (cost\=65946.77..415052.55 rows\=2 width\=62) (actual time\=612.740..612.743 rows\=0.00 loops\=3)||
    204 ||                                            Hash Cond: (toi.order_id \= o.order_id)||
    205 ||                                            Buffers: shared read\=38603||
    206 ||                                            ->  Parallel Seq Scan on ""Ticket_Order_Item"" toi  (cost\=0.00..326137.01 rows\=8750001 width\=62) (never executed)||
    207 ||                                            ->  Parallel Hash  (cost\=65946.76..65946.76 rows\=1 width\=16) (actual time\=612.667..612.667 rows\=0.00 loops\=3)||
    208 ||                                                  Buckets: 1024  Batches: 1  Memory Usage: 0kB||
    209 ||                                                  Buffers: shared read\=38603||
    210 ||                                                  ->  Parallel Seq Scan on ""Ticket_Order"" o  (cost\=0.00..65946.76 rows\=1 width\=16) (actual time\=612.428..612.428 rows\=0.00 loops\=3)||
    211 ||                                                        Filter: (user_id \= 5)||
    212 ||                                                        Rows Removed by Filter: 1750000||
    213 ||                                                        Buffers: shared read\=38603||
    214 ||                                      ->  Materialize  (cost\=0.86..12.91 rows\=1 width\=36) (never executed)||
    215 ||                                            ->  Nested Loop  (cost\=0.86..12.90 rows\=1 width\=36) (never executed)||
    216 ||                                                  ->  Index Scan using ""User_pkey"" on ""User"" u  (cost\=0.43..8.45 rows\=1 width\=28) (never executed)||
    217 ||                                                        Index Cond: (user_id \= 5)||
    218 ||                                                        Index Searches: 0||
    219 ||                                                  ->  Index Only Scan using ""Regular_User_pkey"" on ""Regular_User"" ru  (cost\=0.43..4.45 rows\=1 width\=8) (never executed)||
    220 ||                                                        Index Cond: (user_id \= 5)||
    221 ||                                                        Heap Fetches: 0||
    222 ||                                                        Index Searches: 0||
    223 ||                                ->  Index Scan using ""Ticket_pkey"" on ""Ticket"" t  (cost\=0.44..1.39 rows\=1 width\=16) (never executed)||
    224 ||                                      Index Cond: (ticket_id \= toi.ticket_id)||
    225 ||                                      Index Searches: 0||
    226 ||                          ->  Index Scan using ""Event_Happening_pkey"" on ""Event_Happening"" eh  (cost\=0.29..0.31 rows\=1 width\=24) (never executed)||
    227 ||                                Index Cond: (event_happening_id \= t.event_happening_id)||
    228 ||                                Index Searches: 0||
    229 ||                    ->  Index Scan using ""Event_pkey"" on ""Event"" e  (cost\=0.29..0.37 rows\=1 width\=39) (never executed)||
    230 ||                          Index Cond: (event_id \= eh.event_id)||
    231 ||                          Index Searches: 0||
    232 ||              ->  Index Scan using ""Ticket_Refund_Item_order_item_id_key"" on ""Ticket_Refund_Item"" tri  (cost\=0.43..0.52 rows\=1 width\=24) (never executed)||
    233 ||                    Index Cond: (order_item_id \= toi.order_item_id)||
    234 ||                    Index Searches: 0||
    235 ||        ->  Index Scan using ""Ticket_Refund_pkey"" on ""Ticket_Refund"" tr  (cost\=0.42..0.52 rows\=1 width\=16) (never executed)||
    236 ||              Index Cond: (refund_id \= tri.refund_id)||
    237 ||              Index Searches: 0||
    238 ||Planning:||
    239 ||  Buffers: shared hit\=38 read\=57 dirtied\=3||
    240 ||Planning Time: 29.035 ms||
    241 ||Execution Time: 676.751 ms||
     180||Gather  (cost\=110699.49..459840.66 rows\=4 width\=145) (actual time\=370.701..375.993 rows\=0.00 loops\=1)||
     181||Workers Planned: 2||
     182||Workers Launched: 2||
     183||Buffers: shared read\=82353||
     184||->  Nested Loop Left Join  (cost\=109699.49..458840.26 rows\=2 width\=145) (actual time\=312.925..312.929 rows\=0.00 loops\=3)||
     185||Buffers: shared read\=82353||
     186||->  Nested Loop Left Join  (cost\=109699.07..458836.23 rows\=2 width\=145) (actual time\=312.924..312.928 rows\=0.00 loops\=3)||
     187||Buffers: shared read\=82353||
     188||->  Nested Loop  (cost\=109698.64..458832.18 rows\=2 width\=129) (actual time\=312.923..312.927 rows\=0.00 loops\=3)||
     189||Buffers: shared read\=82353||
     190||->  Nested Loop  (cost\=109698.35..458828.40 rows\=2 width\=98) (actual time\=312.923..312.927 rows\=0.00 loops\=3)||
     191||Buffers: shared read\=82353||
     192||->  Nested Loop  (cost\=109698.07..458824.71 rows\=2 width\=90) (actual time\=312.923..312.926 rows\=0.00 loops\=3)||
     193||Buffers: shared read\=82353||
     194||->  Nested Loop  (cost\=109697.63..458819.48 rows\=2 width\=82) (actual time\=312.922..312.925 rows\=0.00 loops\=3)||
     195||Buffers: shared read\=82353||
     196||->  Parallel Hash Join  (cost\=109696.77..458802.55 rows\=2 width\=62) (actual time\=312.921..312.924 rows\=0.00 loops\=3)||
     197||Hash Cond: (toi.order_id \= o.order_id)||
     198||Buffers: shared read\=82353||
     199||->  Parallel Seq Scan on ""Ticket_Order_Item"" toi  (cost\=0.00..326137.01 rows\=8750001 width\=62) (never executed)||
     200||->  Parallel Hash  (cost\=109696.76..109696.76 rows\=1 width\=16) (actual time\=312.874..312.875 rows\=0.00 loops\=3)||
     201||Buckets: 1024  Batches: 1  Memory Usage: 0kB||
     202||Buffers: shared read\=82353||
     203||->  Parallel Seq Scan on ""Ticket_Order"" o  (cost\=0.00..109696.76 rows\=1 width\=16) (actual time\=312.664..312.664 rows\=0.00 loops\=3)||
     204||Filter: (user_id \= 5)||
     205||Rows Removed by Filter: 1750000||
     206||Buffers: shared read\=82353||
     207||->  Materialize  (cost\=0.86..16.91 rows\=1 width\=36) (never executed)||
     208||->  Nested Loop  (cost\=0.86..16.91 rows\=1 width\=36) (never executed)||
     209||->  Index Scan using ""User_pkey"" on ""User"" u  (cost\=0.43..8.45 rows\=1 width\=28) (never executed)||
     210||Index Cond: (user_id \= 5)||
     211||Filter: is_active||
     212||Index Searches: 0||
     213||->  Index Only Scan using ""Regular_User_pkey"" on ""Regular_User"" ru  (cost\=0.43..8.45 rows\=1 width\=8) (never executed)||
     214||Index Cond: (user_id \= 5)||
     215||Heap Fetches: 0||
     216||Index Searches: 0||
     217||->  Index Scan using ""Ticket_pkey"" on ""Ticket"" t  (cost\=0.44..2.61 rows\=1 width\=16) (never executed)||
     218||Index Cond: (ticket_id \= toi.ticket_id)||
     219||Index Searches: 0||
     220||->  Index Scan using ""Event_Happening_pkey"" on ""Event_Happening"" eh  (cost\=0.29..1.85 rows\=1 width\=24) (never executed)||
     221||Index Cond: (event_happening_id \= t.event_happening_id)||
     222||Index Searches: 0||
     223||->  Index Scan using ""Event_pkey"" on ""Event"" e  (cost\=0.29..1.89 rows\=1 width\=39) (never executed)||
     224||Index Cond: (event_id \= eh.event_id)||
     225||Index Searches: 0||
     226||->  Index Scan using ""Ticket_Refund_Item_order_item_id_key"" on ""Ticket_Refund_Item"" tri  (cost\=0.43..2.02 rows\=1 width\=24) (never executed)||
     227||Index Cond: (order_item_id \= toi.order_item_id)||
     228||Index Searches: 0||
     229||->  Index Scan using ""Ticket_Refund_pkey"" on ""Ticket_Refund"" tr  (cost\=0.42..2.02 rows\=1 width\=16) (never executed)||
     230||Index Cond: (refund_id \= tri.refund_id)||
     231||Index Searches: 0||
     232||Planning||
     233||Buffers: shared hit\=33 read\=44 dirtied\=2||
     234||Planning Time: 13.836 ms||
     235||Execution Time: 376.133 ms||
    242236
    243237 * '''INSERT'''
     
    252246
    253247||= QUERY PLAN =||
    254 ||Insert on ""Ticket_Order_Item""  (cost\=0.00..0.01 rows\=0 width\=0) (actual time\=17.637..17.638 rows\=0.00 loops\=1)||
    255 ||  Buffers: shared hit\=4 read\=3 dirtied\=1||
    256 ||  ->  Result  (cost\=0.00..0.01 rows\=1 width\=556) (actual time\=0.001..0.002 rows\=1.00 loops\=1)||
    257 ||Planning Time: 0.029 ms||
    258 ||Trigger for constraint fk_item_order: time\=0.342 calls\=1||
    259 ||Trigger for constraint fk_item_ticket: time\=0.191 calls\=1||
    260 ||Execution Time: 18.187 ms||
     248||Insert on ""Ticket_Order_Item""  (cost\=0.00..0.01 rows\=0 width\=0) (actual time\=0.049..0.049 rows\=0.00 loops\=1)||
     249||Buffers: shared hit\=5 dirtied\=1||
     250||->  Result  (cost\=0.00..0.01 rows\=1 width\=556) (actual time\=0.001..0.001 rows\=1.00 loops\=1)||
     251||Planning Time: 0.028 ms||
     252||Trigger for constraint fk_item_order: time\=0.251 calls\=1||
     253||Trigger for constraint fk_item_ticket: time\=0.210 calls\=1||
     254||Execution Time: 0.523 ms||
    261255
    262256 * '''UPDATE'''
     
    265259
    266260EXPLAIN ANALYZE
    267 UPDATE "Ticket_Order_Item"
    268 SET qr_code = '3ebd5fa12ec8781d1e9ae4333484984a'
     261UPDATE "Ticket_Order_Item" SET qr_code = '3ebd5fa12ec8781d1e9ae4333484984a'
    269262WHERE order_item_id = 99999999;
    270263
     
    272265
    273266||= QUERY PLAN =||
    274 ||Update on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=0 width\=0) (actual time\=0.051..0.052 rows\=0.00 loops\=1)||
    275 ||  Buffers: shared hit\=7||
    276 ||  ->  Index Scan using ""Ticket_Order_Item_pkey"" on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=1 width\=522) (actual time\=0.023..0.024 rows\=1.00 loops\=1)||
    277 ||        Index Cond: (order_item_id \= 99999999)||
    278 ||        Index Searches: 1||
    279 ||        Buffers: shared hit\=4||
    280 ||Planning Time: 0.137 ms||
    281 ||Execution Time: 0.071 ms||
     267||Update on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=0 width\=0) (actual time\=0.085..0.086 rows\=0.00 loops\=1)||
     268||Buffers: shared hit\=7||
     269||->  Index Scan using ""Ticket_Order_Item_pkey"" on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=1 width\=522) (actual time\=0.039..0.040 rows\=1.00 loops\=1)||
     270||Index Cond: (order_item_id \= 99999999)||
     271||Index Searches: 1||
     272||Buffers: shared hit\=4||
     273||Planning Time: 0.173 ms||
     274||Execution Time: 0.118 ms||
    282275
    283276==== 5. Оптимизација и индексирање:
    284277
    285 За драстично кратење на времето, воведуваме '''B-tree''' индекси врз надворешните клучеви кои ја контролираат хиерархијата на релациите од корисникот па се до ставката на нарачката. Дополнително, се извршува '''ANALYZE''' за стабилизација на статистиките.
     278За драстично кратење на времето, воведени се следните индекси:
     279
     280 * `idx_ticket_order_user_id`: За директно мапирање на корисник кон неговите нарачки.
     281 * `idx_toi_order_id`: За забрзување на поврзувањето на ставки од нарачка.
     282 * `idx_toi_ticket_id`: За брзо поврзување на ставка од нарачка со конкретен билет.
     283
     284Извршен е ANALYZE за обновување на статистиките на планерот.
    286285
    287286{{{
     
    304303==== 6. Резултат по оптимизација:
    305304
    306 По воведувањето на индексите и ажурирањето на статистиката, добиен е најголемиот перформансен бенефит во системот:
    307 
    308  * Времето за '''SELECT''' падна на неверојатни 0.073 ms, што претставува забрзување од над 9.000 пати. Читањето од диск е целосно елиминирано ('''shared read=0'''), а базата сега извршува директен и молскавично брз '''Index Scan''' во RAM меморијата користејќи само 11 мемориски буфери.
    309  * Времето за '''INSERT''' падна на 0.655 ms (околу 27 пати побрзо), со оглед на тоа што проверката на '''foreign key''' констреинтите сега веднаш се резолвира преку новите индексни структури.
    310  * Операцијата '''UPDATE''' ги задржа своите стабилни и конзистентни под-милисекундни перформанси (0.135 ms).
     305Времето за '''SELECT''' е намалено на ~1.24 ms, што претставува забрзување од преку 300 пати. Читањето од диск е сведено на минимум, а сите операции се извршуваат директно во RAM меморијата преку индексните структури. Системот сега работи со конзистентна брзина, дури и под оптоварување.
    311306
    312307 * '''SELECT'''
     
    315310
    316311EXPLAIN ANALYZE
    317 SELECT * FROM "User_Tickets"
     312SELECT *
     313FROM "User_Tickets"
    318314WHERE user_id = 99;
    319315
     
    321317
    322318||= QUERY PLAN =||
    323 ||Nested Loop Left Join  (cost\=3.59..42.94 rows\=4 width\=145) (actual time\=0.070..0.073 rows\=0.00 loops\=1)||
    324 ||  Buffers: shared hit\=11||
    325 ||  ->  Nested Loop Left Join  (cost\=3.17..40.87 rows\=4 width\=145) (actual time\=0.070..0.072 rows\=0.00 loops\=1)||
    326 ||        Buffers: shared hit\=11||
    327 ||        ->  Nested Loop  (cost\=2.74..38.81 rows\=4 width\=129) (actual time\=0.070..0.071 rows\=0.00 loops\=1)||
    328 ||              Buffers: shared hit\=11||
    329 ||              ->  Nested Loop  (cost\=2.46..37.34 rows\=4 width\=98) (actual time\=0.069..0.071 rows\=0.00 loops\=1)||
    330 ||                    Buffers: shared hit\=11||
    331 ||                    ->  Nested Loop  (cost\=2.17..36.09 rows\=4 width\=90) (actual time\=0.069..0.071 rows\=0.00 loops\=1)||
    332 ||                          Buffers: shared hit\=11||
    333 ||                          ->  Nested Loop  (cost\=1.73..30.51 rows\=4 width\=82) (actual time\=0.069..0.070 rows\=0.00 loops\=1)||
    334 ||                                Buffers: shared hit\=11||
    335 ||                                ->  Nested Loop  (cost\=1.29..21.36 rows\=1 width\=36) (actual time\=0.069..0.069 rows\=0.00 loops\=1)||
    336 ||                                      Buffers: shared hit\=11||
    337 ||                                      ->  Nested Loop  (cost\=0.86..12.90 rows\=1 width\=36) (actual time\=0.039..0.041 rows\=1.00 loops\=1)||
    338 ||                                            Buffers: shared hit\=8||
    339 ||                                            ->  Index Scan using ""User_pkey"" on ""User"" u  (cost\=0.43..8.45 rows\=1 width\=28) (actual time\=0.017..0.018 rows\=1.00 loops\=1)||
    340 ||                                                  Index Cond: (user_id \= 99)||
    341 ||                                                  Index Searches: 1||
    342 ||                                                  Buffers: shared hit\=4||
    343 ||                                            ->  Index Only Scan using ""Regular_User_pkey"" on ""Regular_User"" ru  (cost\=0.43..4.45 rows\=1 width\=8) (actual time\=0.018..0.019 rows\=1.00 loops\=1)||
    344 ||                                                  Index Cond: (user_id \= 99)||
    345 ||                                                  Heap Fetches: 0||
    346 ||                                                  Index Searches: 1||
    347 ||                                                  Buffers: shared hit\=4||
    348 ||                                      ->  Index Scan using idx_ticket_order_user_id on ""Ticket_Order"" o  (cost\=0.43..8.44 rows\=1 width\=16) (actual time\=0.027..0.027 rows\=0.00 loops\=1)||
    349 ||                                            Index Cond: (user_id \= 99)||
    350 ||                                            Index Searches: 1||
    351 ||                                            Buffers: shared hit\=3||
    352 ||                                ->  Index Scan using idx_toi_order_id on ""Ticket_Order_Item"" toi  (cost\=0.44..8.89 rows\=26 width\=62) (never executed)||
    353 ||                                      Index Cond: (order_id \= o.order_id)||
    354 ||                                      Index Searches: 0||
    355 ||                          ->  Index Scan using ""Ticket_pkey"" on ""Ticket"" t  (cost\=0.44..1.39 rows\=1 width\=16) (never executed)||
    356 ||                                Index Cond: (ticket_id \= toi.ticket_id)||
    357 ||                                Index Searches: 0||
    358 ||                    ->  Index Scan using ""Event_Happening_pkey"" on ""Event_Happening"" eh  (cost\=0.29..0.31 rows\=1 width\=24) (never executed)||
    359 ||                          Index Cond: (event_happening_id \= t.event_happening_id)||
    360 ||                          Index Searches: 0||
    361 ||              ->  Index Scan using ""Event_pkey"" on ""Event"" e  (cost\=0.29..0.37 rows\=1 width\=39) (never executed)||
    362 ||                    Index Cond: (event_id \= eh.event_id)||
    363 ||                    Index Searches: 0||
    364 ||        ->  Index Scan using ""Ticket_Refund_Item_order_item_id_key"" on ""Ticket_Refund_Item"" tri  (cost\=0.43..0.52 rows\=1 width\=24) (never executed)||
    365 ||              Index Cond: (order_item_id \= toi.order_item_id)||
    366 ||              Index Searches: 0||
    367 ||  ->  Index Scan using ""Ticket_Refund_pkey"" on ""Ticket_Refund"" tr  (cost\=0.42..0.52 rows\=1 width\=16) (never executed)||
    368 ||        Index Cond: (refund_id \= tri.refund_id)||
    369 ||        Index Searches: 0||
    370 ||Planning:||
    371 ||  Buffers: shared hit\=295 read\=8||
    372 ||Planning Time: 74.096 ms||
    373 ||Execution Time: 0.196 ms||
     319||Nested Loop Left Join  (cost\=3.59..75.95 rows\=4 width\=145) (actual time\=1.244..1.247 rows\=0.00 loops\=1)||
     320||Buffers: shared hit\=1 read\=10||
     321||->  Nested Loop Left Join  (cost\=3.17..67.89 rows\=4 width\=145) (actual time\=1.243..1.246 rows\=0.00 loops\=1)||
     322||Buffers: shared hit\=1 read\=10||
     323||->  Nested Loop  (cost\=2.74..59.80 rows\=4 width\=129) (actual time\=1.242..1.245 rows\=0.00 loops\=1)||
     324||Buffers: shared hit\=1 read\=10||
     325||->  Nested Loop  (cost\=2.46..52.24 rows\=4 width\=98) (actual time\=1.242..1.244 rows\=0.00 loops\=1)||
     326||Buffers: shared hit\=1 read\=10||
     327||->  Nested Loop  (cost\=2.17..44.84 rows\=4 width\=90) (actual time\=1.241..1.244 rows\=0.00 loops\=1)||
     328||Buffers: shared hit\=1 read\=10||
     329||->  Nested Loop  (cost\=1.73..34.40 rows\=4 width\=82) (actual time\=1.241..1.243 rows\=0.00 loops\=1)||
     330||Buffers: shared hit\=1 read\=10||
     331||->  Nested Loop  (cost\=1.29..25.36 rows\=1 width\=36) (actual time\=1.240..1.242 rows\=0.00 loops\=1)||
     332||Buffers: shared hit\=1 read\=10||
     333||->  Nested Loop  (cost\=0.86..16.91 rows\=1 width\=36) (actual time\=1.119..1.123 rows\=1.00 loops\=1)||
     334||Buffers: shared hit\=1 read\=7||
     335||->  Index Scan using ""User_pkey"" on ""User"" u  (cost\=0.43..8.45 rows\=1 width\=28) (actual time\=0.716..0.718 rows\=1.00 loops\=1)||
     336||Index Cond: (user_id \= 99)||
     337||Filter: is_active||
     338||Index Searches: 1||
     339||Buffers: shared read\=4||
     340||->  Index Only Scan using ""Regular_User_pkey"" on ""Regular_User"" ru  (cost\=0.43..8.45 rows\=1 width\=8) (actual time\=0.398..0.400 rows\=1.00 loops\=1)||
     341||Index Cond: (user_id \= 99)||
     342||Heap Fetches: 0||
     343||Index Searches: 1||
     344||Buffers: shared hit\=1 read\=3||
     345||->  Index Scan using idx_ticket_order_user_id on ""Ticket_Order"" o  (cost\=0.43..8.44 rows\=1 width\=16) (actual time\=0.116..0.116 rows\=0.00 loops\=1)||
     346||Index Cond: (user_id \= 99)||
     347||Index Searches: 1||
     348||Buffers: shared read\=3||
     349||->  Index Scan using idx_toi_order_id on ""Ticket_Order_Item"" toi  (cost\=0.44..8.82 rows\=22 width\=62) (never executed)||
     350||Index Cond: (order_id \= o.order_id)||
     351||Index Searches: 0||
     352||->  Index Scan using ""Ticket_pkey"" on ""Ticket"" t  (cost\=0.44..2.61 rows\=1 width\=16) (never executed)||
     353||Index Cond: (ticket_id \= toi.ticket_id)||
     354||Index Searches: 0||
     355||->  Index Scan using ""Event_Happening_pkey"" on ""Event_Happening"" eh  (cost\=0.29..1.85 rows\=1 width\=24) (never executed)||
     356||Index Cond: (event_happening_id \= t.event_happening_id)||
     357||Index Searches: 0||
     358||->  Index Scan using ""Event_pkey"" on ""Event"" e  (cost\=0.29..1.89 rows\=1 width\=39) (never executed)||
     359||Index Cond: (event_id \= eh.event_id)||
     360||Index Searches: 0||
     361||->  Index Scan using ""Ticket_Refund_Item_order_item_id_key"" on ""Ticket_Refund_Item"" tri  (cost\=0.43..2.02 rows\=1 width\=24) (never executed)||
     362||Index Cond: (order_item_id \= toi.order_item_id)||
     363||Index Searches: 0||
     364||->  Index Scan using ""Ticket_Refund_pkey"" on ""Ticket_Refund"" tr  (cost\=0.42..2.02 rows\=1 width\=16) (never executed)||
     365||Index Cond: (refund_id \= tri.refund_id)||
     366||Index Searches: 0||
     367||Planning||
     368||Buffers: shared hit\=264 read\=37||
     369||Planning Time: 41.864 ms||
     370||Execution Time: 1.392 ms||
    374371
    375372 * '''INSERT'''
     
    384381
    385382||= QUERY PLAN =||
    386 ||Insert on ""Ticket_Order_Item""  (cost\=0.00..0.01 rows\=0 width\=0) (actual time\=0.307..0.307 rows\=0.00 loops\=1)||
    387 ||  Buffers: shared hit\=12 dirtied\=3||
    388 ||  ->  Result  (cost\=0.00..0.01 rows\=1 width\=556) (actual time\=0.001..0.001 rows\=1.00 loops\=1)||
    389 ||Planning Time: 0.032 ms||
    390 ||Trigger for constraint fk_item_order: time\=0.200 calls\=1||
    391 ||Trigger for constraint fk_item_ticket: time\=0.132 calls\=1||
    392 ||Execution Time: 0.655 ms||
     383||Insert on ""Ticket_Order_Item""  (cost\=0.00..0.01 rows\=0 width\=0) (actual time\=0.273..0.273 rows\=0.00 loops\=1)||
     384||Buffers: shared hit\=11 read\=3 dirtied\=3||
     385||->  Result  (cost\=0.00..0.01 rows\=1 width\=556) (actual time\=0.001..0.001 rows\=1.00 loops\=1)||
     386||Planning Time: 0.031 ms||
     387||Trigger for constraint fk_item_order: time\=0.241 calls\=1||
     388||Trigger for constraint fk_item_ticket: time\=2.938 calls\=1||
     389||Execution Time: 3.470 ms||
    393390
    394391 * '''UPDATE'''
     
    397394
    398395EXPLAIN ANALYZE
    399 UPDATE "Ticket_Order_Item"
    400 SET qr_code = '3ebc5fd20ec8681d1e9ee5733484984a'
    401 WHERE order_item_id = 77777777;
    402 
    403 }}}
    404 
    405 ||= QUERY PLAN =||
    406 ||Update on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=0 width\=0) (actual time\=0.091..0.091 rows\=0.00 loops\=1)||
    407 ||  Buffers: shared hit\=7||
    408 ||  ->  Index Scan using ""Ticket_Order_Item_pkey"" on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=1 width\=522) (actual time\=0.022..0.023 rows\=1.00 loops\=1)||
    409 ||        Index Cond: (order_item_id \= 77777777)||
    410 ||        Index Searches: 1||
    411 ||        Buffers: shared hit\=4||
    412 ||Planning Time: 0.120 ms||
    413 ||Execution Time: 0.135 ms||
     396UPDATE "Ticket_Order_Item" SET qr_code = '3ebc5fd20ec8681d1e9ee5733484984a' WHERE order_item_id = 77777777;
     397
     398}}}
     399
     400||= QUERY PLAN =||
     401||Update on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=0 width\=0) (actual time\=0.102..0.103 rows\=0.00 loops\=1)||
     402||Buffers: shared hit\=7||
     403||->  Index Scan using ""Ticket_Order_Item_pkey"" on ""Ticket_Order_Item""  (cost\=0.44..8.46 rows\=1 width\=522) (actual time\=0.049..0.051 rows\=1.00 loops\=1)||
     404||Index Cond: (order_item_id \= 77777777)||
     405||Index Searches: 1||
     406||Buffers: shared hit\=4||
     407||Planning Time: 0.160 ms||
     408||Execution Time: 0.179 ms||
    414409
    415410