wiki:QueryOptimization

Version 6 (modified by 231018, 12 days ago) ( diff )

--

Анализа на View1: Прекршоци денес

Прашалниците кои ќе ги тестираме се следните:

-- 1A: приказ на сите прекршоци евидентирани на последниот датум
SELECT *
FROM vw_prekrsoci_denes
WHERE registarska_oznaka = 'SR-2625-AC';

-- 1B: пребарување на прекршоци според регистарска ознака
EXPLAIN ANALYZE
SELECT *
FROM vw_prekrsoci_denes
WHERE registarska_oznaka = 'SR-2625-AC';

Време на извршување без индекси

1A - 6259 ms

При извршување на прашалникот:

SELECT *
FROM vw_prekrsoci_denes
WHERE registarska_oznaka = 'SR-2625-AC';

Прашалникот успешно ги прикажува прекршоците поврзани со возилото со регистарска ознака SR-2625-AC, заедно со информациите за зоната, дозволената брзина и сторителот на прекршокот.

При извршување на прашалникот SELECT * FROM vw_prekrsoci_denes WHERE registarska_oznaka = 'SR-2625-AC';, DataGrip прикажува време на извршување од приближно 7 секунди.

Иако се пребарува само едно возило, погледот поврзува повеќе табели (Prekrsok, Kamera, Lokacija, Zona, Prekrsok_Vozilo, Vozilo, Prekrsok_Storitel и Gragjanin), поради што PostgreSQL обработува поголем број записи пред да ги врати конечните резултати.

1B - 2565.134 ms

Nested Loop Left Join  (cost=81647.37..91337.78 rows=1 width=156) (actual time=133.585..2564.780 rows=1290 loops=1)
  InitPlan 1
    ->  Finalize Aggregate  (cost=80636.78..80636.79 rows=1 width=4) (actual time=127.885..128.003 rows=1 loops=1)
          ->  Gather  (cost=80636.37..80636.77 rows=4 width=4) (actual time=127.726..127.994 rows=5 loops=1)
                Workers Planned: 4
                Workers Launched: 4
                ->  Partial Aggregate  (cost=79636.37..79636.38 rows=1 width=4) (actual time=96.102..96.103 rows=1 loops=5)
                      ->  Parallel Seq Scan on prekrsok  (cost=0.00..78654.69 rows=392669 width=4) (actual time=0.025..69.617 rows=200002 loops=5)
  ->  Nested Loop Left Join  (cost=1010.15..10700.39 rows=1 width=142) (actual time=133.560..2548.091 rows=1290 loops=1)
        ->  Nested Loop Left Join  (cost=1009.72..10696.01 rows=1 width=128) (actual time=133.544..2543.391 rows=645 loops=1)
              ->  Nested Loop Left Join  (cost=1009.44..10695.62 rows=1 width=113) (actual time=133.533..2540.561 rows=645 loops=1)
                    ->  Nested Loop Left Join  (cost=1009.16..10695.28 rows=1 width=113) (actual time=133.521..2537.787 rows=645 loops=1)
                          ->  Nested Loop  (cost=1008.88..10694.83 rows=1 width=113) (actual time=133.506..2534.805 rows=645 loops=1)
                                ->  Gather  (cost=1008.46..10694.03 rows=1 width=14) (actual time=0.480..128.971 rows=1000010 loops=1)
                                      Workers Planned: 2
                                      Workers Launched: 2
                                      ->  Hash Join  (cost=8.46..9693.93 rows=1 width=14) (actual time=0.204..114.102 rows=333337 loops=3)
                                            Hash Cond: (pv.vozilo_id = v.vozilo_id)
                                            ->  Parallel Seq Scan on prekrsok_vozilo pv  (cost=0.00..8591.71 rows=416671 width=8) (actual time=0.029..39.040 rows=333337 loops=3)
                                            ->  Hash  (cost=8.45..8.45 rows=1 width=14) (actual time=0.082..0.083 rows=1 loops=3)
                                                  Buckets: 1024  Batches: 1  Memory Usage: 9kB
                                                  ->  Index Scan using uq_vozilo_registarska on vozilo v  (cost=0.43..8.45 rows=1 width=14) (actual time=0.074..0.075 rows=1 loops=3)
                                                        Index Cond: ((registarska_oznaka)::text = 'SR-2625-AC'::text)
                                ->  Index Scan using prekrsok_pkey on prekrsok p  (cost=0.43..0.80 rows=1 width=103) (actual time=0.002..0.002 rows=0 loops=1000010)
                                      Index Cond: (prekrsok_id = pv.prekrsok_id)
                                      Filter: (datum = (InitPlan 1).col1)
                                      Rows Removed by Filter: 1
                          ->  Index Scan using kamera_pkey on kamera k  (cost=0.28..0.44 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=645)
                                Index Cond: (kamera_id = p.kamera_id)
                    ->  Index Scan using lokacija_pkey on lokacija l  (cost=0.28..0.35 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=645)
                          Index Cond: (lokacija_id = k.lokacija_id)
              ->  Index Scan using zona_pkey on zona z  (cost=0.28..0.39 rows=1 width=23) (actual time=0.003..0.003 rows=1 loops=645)
                    Index Cond: (zona_id = l.zona_id)
        ->  Index Only Scan using prekrsok_storitel_pkey on prekrsok_storitel ps  (cost=0.43..4.36 rows=2 width=18) (actual time=0.005..0.006 rows=2 loops=645)
              Index Cond: (prekrsok_id = p.prekrsok_id)
              Heap Fetches: 0
  ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..0.59 rows=1 width=42) (actual time=0.012..0.012 rows=1 loops=1290)
        Index Cond: (embg = (ps.storitel_embg)::bpchar)
Planning Time: 2.847 ms
Execution Time: 2565.134 ms

Време на извршување со индекси

1A - 3896 ms (беше 6259 ms)

1B - 834 ms (беше 2565.134 ms)

Nested Loop Left Join  (cost=12.68..7792.73 rows=2 width=156) (actual time=0.351..376.504 rows=1290 loops=1)
  InitPlan 2
    ->  Result  (cost=0.45..0.46 rows=1 width=4) (actual time=0.018..0.020 rows=1 loops=1)
          InitPlan 1
            ->  Limit  (cost=0.42..0.45 rows=1 width=4) (actual time=0.016..0.017 rows=1 loops=1)
                  ->  Index Only Scan Backward using idx_prekrsok_datum on prekrsok  (cost=0.42..21048.60 rows=1000010 width=4) (actual time=0.015..0.016 rows=1 loops=1)
                        Index Cond: (datum IS NOT NULL)
                        Heap Fetches: 0
  ->  Nested Loop Left Join  (cost=11.80..7791.09 rows=2 width=142) (actual time=0.324..349.304 rows=1290 loops=1)
        ->  Nested Loop Left Join  (cost=11.37..7786.67 rows=1 width=128) (actual time=0.297..340.552 rows=645 loops=1)
              ->  Nested Loop Left Join  (cost=11.09..7786.29 rows=1 width=113) (actual time=0.253..338.210 rows=645 loops=1)
                    ->  Nested Loop Left Join  (cost=10.81..7785.94 rows=1 width=113) (actual time=0.244..335.905 rows=645 loops=1)
                          ->  Nested Loop  (cost=10.53..7785.41 rows=1 width=113) (actual time=0.236..333.094 rows=645 loops=1)
                                Join Filter: (pv.vozilo_id = v.vozilo_id)
                                ->  Index Scan using uq_vozilo_registarska on vozilo v  (cost=0.43..8.45 rows=1 width=14) (actual time=0.024..0.026 rows=1 loops=1)
                                      Index Cond: ((registarska_oznaka)::text = 'SR-2625-AC'::text)
                                ->  Nested Loop  (cost=10.10..7768.49 rows=678 width=107) (actual time=0.188..332.815 rows=645 loops=1)
                                      ->  Bitmap Heap Scan on prekrsok p  (cost=9.68..2525.70 rows=678 width=103) (actual time=0.174..4.152 rows=645 loops=1)
                                            Recheck Cond: (datum = (InitPlan 2).col1)
                                            Heap Blocks: exact=634
                                            ->  Bitmap Index Scan on idx_prekrsok_datum  (cost=0.00..9.51 rows=678 width=0) (actual time=0.075..0.075 rows=645 loops=1)
                                                  Index Cond: (datum = (InitPlan 2).col1)
                                      ->  Index Only Scan using prekrsok_vozilo_pkey on prekrsok_vozilo pv  (cost=0.42..7.72 rows=1 width=8) (actual time=0.508..0.508 rows=1 loops=645)
                                            Index Cond: (prekrsok_id = p.prekrsok_id)
                                            Heap Fetches: 645
                          ->  Index Scan using kamera_pkey on kamera k  (cost=0.28..0.53 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=645)
                                Index Cond: (kamera_id = p.kamera_id)
                    ->  Index Scan using lokacija_pkey on lokacija l  (cost=0.28..0.35 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=645)
                          Index Cond: (lokacija_id = k.lokacija_id)
              ->  Index Scan using zona_pkey on zona z  (cost=0.28..0.39 rows=1 width=23) (actual time=0.003..0.003 rows=1 loops=645)
                    Index Cond: (zona_id = l.zona_id)
        ->  Index Only Scan using prekrsok_storitel_pkey on prekrsok_storitel ps  (cost=0.43..4.40 rows=2 width=18) (actual time=0.011..0.013 rows=2 loops=645)
              Index Cond: (prekrsok_id = p.prekrsok_id)
              Heap Fetches: 0
  ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..0.59 rows=1 width=42) (actual time=0.020..0.020 rows=1 loops=1290)
        Index Cond: (embg = (ps.storitel_embg)::bpchar)
Planning Time: 2.778 ms
Execution Time: 376.778 ms

По креирањето на индексот idx_prekrsok_datum, повторно беше извршен истиот прашалник врз погледот vw_prekrsoci_denes.

Времето на извршување на обичниот SELECT се намали од 6259 ms на 3896 ms, додека времето на EXPLAIN ANALYZE се намали од 2565.134 ms на 834 ms. Ова покажува дека индексот има позитивен ефект врз извршувањето на прашалникот.

Иако прашалникот сè уште поврзува повеќе табели, по оптимизацијата времето е значително подобрено и е поблиску до прифатливиот праг.

Анализа на View2: Неплатени казни во последните 2 недели

Прашалниците кои ќе ги тестираме се следните:

-- 2A: приказ на неплатена казна според идентификатор
SELECT *
FROM vw_neplateni_kazni_posledni_2_nedeli
WHERE kazna_id = 523;

-- 2B: анализа на планот на извршување за неплатена казна според идентификатор
EXPLAIN ANALYZE
SELECT *
FROM vw_neplateni_kazni_posledni_2_nedeli
WHERE kazna_id = 523;

Време на извршување без индекси

2A - 1246 ms

При извршување на прашалникот:

SELECT *
FROM vw_neplateni_kazni_posledni_2_nedeli
WHERE kazna_id = 523;

Прашалникот се користи за пребарување на конкретна неплатена казна според нејзиниот идентификатор. Во овој случај, DataGrip не враќа редови за kazna_id = 523, бидејќи оваа казна не ги исполнува условите на погледот. При извршување на прашалникот, DataGrip прикажува време на извршување од 1246 ms, односно приближно 1.2 секунди.

2B - 430.601 ms

Nested Loop Left Join  (cost=192893.72..272550.73 rows=1 width=141) (actual time=419.459..428.078 rows=0 loops=1)
  InitPlan 1
    ->  Finalize Aggregate  (cost=95945.78..95945.79 rows=1 width=8) (actual time=397.322..405.935 rows=1 loops=1)
          ->  Gather  (cost=95945.36..95945.77 rows=4 width=4) (actual time=397.111..405.907 rows=5 loops=1)
                Workers Planned: 4
                Workers Launched: 4
                ->  Partial Aggregate  (cost=94945.36..94945.37 rows=1 width=4) (actual time=362.874..362.875 rows=1 loops=5)
                      ->  Parallel Seq Scan on kazna  (cost=0.00..88695.29 rows=2500029 width=4) (actual time=0.063..183.068 rows=2000000 loops=5)
  InitPlan 2
    ->  Finalize Aggregate  (cost=95945.78..95945.79 rows=1 width=4) (never executed)
          ->  Gather  (cost=95945.36..95945.77 rows=4 width=4) (never executed)
                Workers Planned: 4
                Workers Launched: 0
                ->  Partial Aggregate  (cost=94945.36..94945.37 rows=1 width=4) (never executed)
                      ->  Parallel Seq Scan on kazna kazna_1  (cost=0.00..88695.29 rows=2500029 width=4) (never executed)
  ->  Nested Loop Left Join  (cost=1001.71..80658.46 rows=1 width=135) (actual time=419.458..419.461 rows=0 loops=1)
        ->  Nested Loop Left Join  (cost=1001.29..80650.01 rows=1 width=131) (actual time=419.458..419.460 rows=0 loops=1)
              ->  Nested Loop Left Join  (cost=1000.86..80649.42 rows=1 width=117) (actual time=419.457..419.459 rows=0 loops=1)
                    ->  Nested Loop  (cost=1000.43..80644.94 rows=1 width=103) (actual time=419.457..419.458 rows=0 loops=1)
                          ->  Index Scan using kazna_pkey on kazna k  (cost=0.43..8.46 rows=1 width=16) (actual time=419.456..419.456 rows=0 loops=1)
                                Index Cond: (kazna_id = 523)
                                Filter: ((rok_na_plakanje >= (InitPlan 1).col1) AND (rok_na_plakanje <= (InitPlan 2).col1) AND (status = 0))
                                Rows Removed by Filter: 1
                          ->  Gather  (cost=1000.00..80636.47 rows=1 width=91) (never executed)
                                Workers Planned: 4
                                Workers Launched: 0
                                ->  Parallel Seq Scan on prekrsok p  (cost=0.00..79636.37 rows=1 width=91) (never executed)
                                      Filter: (kazna_id = 523)
                    ->  Index Only Scan using prekrsok_storitel_pkey on prekrsok_storitel ps  (cost=0.43..4.46 rows=2 width=18) (never executed)
                          Index Cond: (prekrsok_id = p.prekrsok_id)
                          Heap Fetches: 0
              ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..0.59 rows=1 width=42) (never executed)
                    Index Cond: (embg = (ps.storitel_embg)::bpchar)
        ->  Index Only Scan using prekrsok_vozilo_pkey on prekrsok_vozilo pv  (cost=0.42..8.44 rows=1 width=8) (never executed)
              Index Cond: (prekrsok_id = p.prekrsok_id)
              Heap Fetches: 0
  ->  Index Scan using vozilo_pkey on vozilo v  (cost=0.43..0.68 rows=1 width=14) (never executed)
        Index Cond: (vozilo_id = pv.vozilo_id)
Planning Time: 1.388 ms
JIT:
  Functions: 48
"  Options: Inlining false, Optimization false, Expressions true, Deforming true"
"  Timing: Generation 4.036 ms (Deform 1.421 ms), Inlining 0.000 ms, Optimization 2.244 ms, Emission 43.042 ms, Total 49.322 ms"
Execution Time: 430.601 ms

Време на извршување со индекси

2A - 1822 ms (беше 1246 ms)

При повторно извршување на прашалникот по креирање на индексот, DataGrip прикажува време на извршување од 1822 ms. Прашалникот не враќа редови, бидејќи казната со kazna_id = 523 не ги исполнува условите на погледот.

2B - 950.735 (беше 430.601 ms)

Gather  (cost=192893.00..270766.77 rows=2 width=141) (actual time=936.691..948.469 rows=0 loops=1)
  Workers Planned: 4
  Workers Launched: 4
  InitPlan 1
    ->  Finalize Aggregate  (cost=95945.42..95945.43 rows=1 width=8) (actual time=400.346..400.476 rows=1 loops=1)
          ->  Gather  (cost=95945.00..95945.41 rows=4 width=4) (actual time=399.914..400.436 rows=5 loops=1)
                Workers Planned: 4
                Workers Launched: 4
                ->  Partial Aggregate  (cost=94945.00..94945.01 rows=1 width=4) (actual time=365.516..365.518 rows=1 loops=5)
                      ->  Parallel Seq Scan on kazna  (cost=0.00..88695.00 rows=2500000 width=4) (actual time=0.056..180.906 rows=2000000 loops=5)
  InitPlan 2
    ->  Finalize Aggregate  (cost=95945.42..95945.43 rows=1 width=4) (actual time=393.098..393.178 rows=1 loops=1)
          ->  Gather  (cost=95945.00..95945.41 rows=4 width=4) (actual time=392.880..393.151 rows=5 loops=1)
                Workers Planned: 4
                Workers Launched: 4
                ->  Partial Aggregate  (cost=94945.00..94945.01 rows=1 width=4) (actual time=360.995..360.996 rows=1 loops=5)
                      ->  Parallel Seq Scan on kazna kazna_1  (cost=0.00..88695.00 rows=2500000 width=4) (actual time=0.060..180.915 rows=2000000 loops=5)
  ->  Nested Loop Left Join  (cost=2.14..77875.71 rows=1 width=141) (actual time=107.787..107.791 rows=0 loops=5)
        ->  Nested Loop Left Join  (cost=1.72..77875.03 rows=1 width=135) (actual time=107.787..107.790 rows=0 loops=5)
              ->  Nested Loop Left Join  (cost=1.29..77866.58 rows=1 width=131) (actual time=107.786..107.789 rows=0 loops=5)
                    ->  Nested Loop Left Join  (cost=0.86..77865.98 rows=1 width=117) (actual time=107.786..107.788 rows=0 loops=5)
                          ->  Nested Loop  (cost=0.43..77861.50 rows=1 width=103) (actual time=107.785..107.787 rows=0 loops=5)
                                ->  Parallel Seq Scan on prekrsok p  (cost=0.00..77853.03 rows=1 width=91) (actual time=101.813..107.757 rows=0 loops=5)
                                      Filter: (kazna_id = 523)
                                      Rows Removed by Filter: 200002
                                ->  Index Scan using kazna_pkey on kazna k  (cost=0.43..8.46 rows=1 width=16) (actual time=0.135..0.135 rows=0 loops=1)
                                      Index Cond: (kazna_id = 523)
                                      Filter: ((rok_na_plakanje >= (InitPlan 1).col1) AND (rok_na_plakanje <= (InitPlan 2).col1) AND (status = 0))
                                      Rows Removed by Filter: 1
                          ->  Index Only Scan using prekrsok_storitel_pkey on prekrsok_storitel ps  (cost=0.43..4.46 rows=2 width=18) (never executed)
                                Index Cond: (prekrsok_id = p.prekrsok_id)
                                Heap Fetches: 0
                    ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..0.59 rows=1 width=42) (never executed)
                          Index Cond: (embg = (ps.storitel_embg)::bpchar)
              ->  Index Only Scan using prekrsok_vozilo_pkey on prekrsok_vozilo pv  (cost=0.42..8.44 rows=1 width=8) (never executed)
                    Index Cond: (prekrsok_id = p.prekrsok_id)
                    Heap Fetches: 0
        ->  Index Scan using vozilo_pkey on vozilo v  (cost=0.43..0.68 rows=1 width=14) (never executed)
              Index Cond: (vozilo_id = pv.vozilo_id)
Planning Time: 1.577 ms
JIT:
  Functions: 159
"  Options: Inlining false, Optimization false, Expressions true, Deforming true"
"  Timing: Generation 13.514 ms (Deform 5.247 ms), Inlining 0.000 ms, Optimization 6.953 ms, Emission 136.174 ms, Total 156.641 ms"
Execution Time: 950.735 ms

За овој поглед беше креиран индексот idx_kazna_status, бидејќи погледот филтрира казни според нивниот статус.

Во овој случај, по креирањето на индексот не се добива подобрување на времето на извршување. Причината е што прашалникот дополнително филтрира според kazna_id = 523, а kazna_id е примарен клуч и PostgreSQL веќе користи индекс преку kazna_pkey.

Затоа новиот индекс idx_kazna_status не е пресуден за овој конкретен прашалник. Бидејќи времето на извршување е околу 1.2 секунди, прашалникот сè уште се смета за прифатлив и не е потребна дополнителна оптимизација.

Анализа на View3: Локации со најмногу прекршоци

Прашалниците кои ќе ги тестираме се следните:

-- 3A: приказ на локации со прекршоци во конкретна зона
SELECT *
FROM vw_lokacii_so_najmnogu_prekrsoci
WHERE zona = 'Centar';

-- 3B: анализа на планот на извршување за локации со прекршоци во конкретна зона
EXPLAIN ANALYZE
SELECT *
FROM vw_lokacii_so_najmnogu_prekrsoci
WHERE zona = 'Centar';

Време на извршување без индекси

3A - 109 ms

Прашалникот се користи за приказ на локации во конкретна зона и бројот на прекршоци евидентирани на тие локации.

Во овој случај, DataGrip не враќа редови за зоната Centar, бидејќи таква зона не постои во резултатите од погледот.

При извршување на прашалникот, DataGrip прикажува време на извршување од 109 ms.

3B - 0.430 ms

GroupAggregate  (cost=96565.40..96574.57 rows=524 width=39) (actual time=0.357..0.360 rows=0 loops=1)
  Group Key: l.lokacija_id
  ->  Sort  (cost=96565.40..96566.71 rows=524 width=35) (actual time=0.355..0.358 rows=0 loops=1)
        Sort Key: l.lokacija_id
        Sort Method: quicksort  Memory: 25kB
        ->  Hash Right Join  (cost=211.68..96541.73 rows=524 width=35) (actual time=0.350..0.353 rows=0 loops=1)
              Hash Cond: (p.kamera_id = k.kamera_id)
              ->  Seq Scan on prekrsok p  (cost=0.00..90434.77 rows=1570677 width=8) (never executed)
              ->  Hash  (cost=211.67..211.67 rows=1 width=35) (actual time=0.344..0.346 rows=0 loops=1)
                    Buckets: 1024  Batches: 1  Memory Usage: 8kB
                    ->  Hash Right Join  (cost=150.41..211.67 rows=1 width=35) (actual time=0.343..0.345 rows=0 loops=1)
                          Hash Cond: (k.lokacija_id = l.lokacija_id)
                          ->  Seq Scan on kamera k  (cost=0.00..50.00 rows=3000 width=8) (never executed)
                          ->  Hash  (cost=150.40..150.40 rows=1 width=31) (actual time=0.339..0.341 rows=0 loops=1)
                                Buckets: 1024  Batches: 1  Memory Usage: 8kB
                                ->  Hash Join  (cost=86.51..150.40 rows=1 width=31) (actual time=0.339..0.340 rows=0 loops=1)
                                      Hash Cond: (l.zona_id = z.zona_id)
                                      ->  Seq Scan on lokacija l  (cost=0.00..56.00 rows=3000 width=20) (actual time=0.011..0.011 rows=1 loops=1)
                                      ->  Hash  (cost=86.50..86.50 rows=1 width=19) (actual time=0.322..0.323 rows=0 loops=1)
                                            Buckets: 1024  Batches: 1  Memory Usage: 8kB
                                            ->  Seq Scan on zona z  (cost=0.00..86.50 rows=1 width=19) (actual time=0.322..0.322 rows=0 loops=1)
                                                  Filter: ((ime)::text = 'Centar'::text)
                                                  Rows Removed by Filter: 3000
Planning Time: 0.611 ms
Execution Time: 0.430 ms

Анализа на View4: Истечени регистрации

Прашалниците кои ќе ги тестираме се следните:

-- 4A: приказ на истечена регистрација според регистарска ознака
SELECT *
FROM vw_isteceni_registracii
WHERE registarska_oznaka = 'VE-135-AA';

-- 4B: анализа на планот на извршување за истечена регистрација според регистарска ознака
EXPLAIN ANALYZE
SELECT *
FROM vw_isteceni_registracii
WHERE registarska_oznaka = 'VE-135-AA';

Време на извршување без индекси

4A - 618 ms

При извршување на прашалникот:

SELECT *
FROM vw_isteceni_registracii
WHERE registarska_oznaka = 'VE-135-AA';

Прашалникот успешно прикажува истечена регистрација за возилото со регистарска ознака VE-135-AA, заедно со податоците за регистрацијата, возилото и сопственикот.

При извршување на прашалникот, DataGrip прикажува време на извршување од 618 ms.

4B - 300.887 ms

Gather  (cost=1008.88..74422.27 rows=2 width=102) (actual time=295.897..300.834 rows=1 loops=1)
  Workers Planned: 4
  Workers Launched: 4
  ->  Nested Loop Left Join  (cost=8.88..73422.07 rows=1 width=102) (actual time=277.098..288.605 rows=0 loops=5)
        ->  Hash Join  (cost=8.46..73421.51 rows=1 width=74) (actual time=277.068..288.574 rows=0 loops=5)
              Hash Cond: (r.vozilovozilo_id = v.vozilo_id)
              ->  Parallel Seq Scan on registracija r  (cost=0.00..71605.81 rows=688470 width=38) (actual time=10.031..215.222 rows=911932 loops=5)
                    Filter: (datum_istekuvanje < CURRENT_DATE)
                    Rows Removed by Filter: 250862
              ->  Hash  (cost=8.45..8.45 rows=1 width=40) (actual time=0.077..0.078 rows=1 loops=5)
                    Buckets: 1024  Batches: 1  Memory Usage: 9kB
                    ->  Index Scan using uq_vozilo_registarska on vozilo v  (cost=0.43..8.45 rows=1 width=40) (actual time=0.069..0.071 rows=1 loops=5)
                          Index Cond: ((registarska_oznaka)::text = 'VE-135-AA'::text)
        ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..0.55 rows=1 width=42) (actual time=0.138..0.138 rows=1 loops=1)
              Index Cond: (embg = (r.sopstvenikembg)::bpchar)
Planning Time: 0.583 ms
Execution Time: 300.887 ms

Анализа на View5: Граѓани со најмногу прекршоци

Прашалниците кои ќе ги тестираме се следните:

-- 5A: приказ на бројот на прекршоци за конкретен граѓанин
SELECT *
FROM vw_gragjani_so_najmnogu_prekrsoci
WHERE embg = '3006956460025';

-- 5B: анализа на планот на извршување за конкретен граѓанин
EXPLAIN ANALYZE
SELECT *
FROM vw_gragjani_so_najmnogu_prekrsoci
WHERE embg = '3006956460025';

Време на извршување без индекси

5A - 433 ms

При извршување на прашалникот:

SELECT *
FROM vw_gragjani_so_najmnogu_prekrsoci
WHERE embg = '3006956460025';

Прашалникот успешно го прикажува бројот на прекршоци за граѓанинот со ЕМБГ 3006956460025.

При извршување на прашалникот, DataGrip прикажува време на извршување од 433 ms.

5B - 143 ms

GroupAggregate  (cost=1000.43..44123.49 rows=1 width=50) (actual time=73.505..78.493 rows=1 loops=1)
  ->  Nested Loop Left Join  (cost=1000.43..44123.48 rows=2 width=46) (actual time=10.174..78.482 rows=1 loops=1)
        ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..8.45 rows=1 width=42) (actual time=0.027..0.033 rows=1 loops=1)
              Index Cond: (embg = '3006956460025'::bpchar)
        ->  Gather  (cost=1000.00..44115.01 rows=2 width=18) (actual time=10.143..78.443 rows=1 loops=1)
              Workers Planned: 4
              Workers Launched: 4
              ->  Parallel Seq Scan on prekrsok_storitel ps  (cost=0.00..43114.81 rows=1 width=18) (actual time=54.779..67.379 rows=0 loops=5)
                    Filter: ((storitel_embg)::bpchar = '3006956460025'::bpchar)
                    Rows Removed by Filter: 400004
Planning Time: 0.251 ms
Execution Time: 78.542 ms

Време на извршување со индекси:

5A - 898 ms (беше 433 ms)

При повторно извршување на прашалникот по креирање на индексот, DataGrip прикажува време на извршување од 898 ms. Во овој случај времето не е намалено кај обичниот SELECT, но прашалникот и понатаму се извршува во прифатливо време.

5B - 107.553 ms (беше 78.542 ms)

GroupAggregate  (cost=1000.43..44134.74 rows=1 width=50) (actual time=99.588..107.507 rows=1 loops=1)
  ->  Nested Loop Left Join  (cost=1000.43..44134.73 rows=2 width=46) (actual time=19.063..107.495 rows=1 loops=1)
        ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..8.45 rows=1 width=42) (actual time=0.026..0.032 rows=1 loops=1)
              Index Cond: (embg = '3006956460025'::bpchar)
        ->  Gather  (cost=1000.00..44126.26 rows=2 width=18) (actual time=19.033..107.457 rows=1 loops=1)
              Workers Planned: 4
              Workers Launched: 4
              ->  Parallel Seq Scan on prekrsok_storitel ps  (cost=0.00..43126.06 rows=1 width=18) (actual time=51.393..67.470 rows=0 loops=5)
                    Filter: ((storitel_embg)::bpchar = '3006956460025'::bpchar)
                    Rows Removed by Filter: 400004
Planning Time: 0.258 ms
Execution Time: 107.553 ms

Иако беше креиран индексот idx_prekrsok_storitel_embg, PostgreSQL продолжува да користи Parallel Seq Scan врз табелата Prekrsok_Storitel. Поради тоа не се забележува значително подобрување на перформансите. Сепак, времето на извршување останува многу мало и прифатливо.

Анализа на View6: Неактивни камери

Прашалниците кои ќе ги тестираме се следните:

-- 6A: приказ на неактивни камери во конкретна зона
SELECT *
FROM vw_neaktivni_kameri
WHERE zona = 'uchilishna zona';

-- 6B: анализа на планот на извршување за неактивни камери во конкретна зона
EXPLAIN ANALYZE
SELECT *
FROM vw_neaktivni_kameri
WHERE zona = 'uchilishna zona';
  1. Примарен филтер за погледот vw_neaktivni_kameri ќе биде според zona или tip_kamera. Погледот ќе се користи за брз преглед на камери кои не се активни во одредена зона.
  1. Примарен случај на употреба ќе биде следење на неисправни, исклучени или неактивни камери. За овој поглед перформансите се важни бидејќи се поврзуваат табелите Kamera, Lokacija, Zona и TipKamera.

Време на извршување без индекси

6A - 72 ms

При извршување на прашалникот:

SELECT *
FROM vw_neaktivni_kameri
WHERE zona = 'uchilishna zona';

Прашалникот успешно прикажува неактивни камери во зоната uchilishna zona, заедно со податоци за улицата, статусот и типот на камерата.

При извршување на прашалникот, DataGrip прикажува време на извршување од 72 ms.

6B - 2.689 ms

Nested Loop Left Join  (cost=158.66..246.66 rows=323 width=257) (actual time=1.282..2.613 rows=34 loops=1)
  ->  Hash Join  (cost=158.51..237.93 rows=323 width=43) (actual time=1.263..2.574 rows=34 loops=1)
        Hash Cond: (k.lokacija_id = l.lokacija_id)
        ->  Seq Scan on kamera k  (cost=0.00..65.00 rows=2985 width=20) (actual time=0.034..1.323 rows=309 loops=1)
              Filter: (lower((status)::text) <> 'aktivna'::text)
              Rows Removed by Filter: 2691
        ->  Hash  (cost=154.45..154.45 rows=325 width=31) (actual time=1.195..1.197 rows=325 loops=1)
              Buckets: 1024  Batches: 1  Memory Usage: 30kB
              ->  Hash Join  (cost=90.56..154.45 rows=325 width=31) (actual time=0.432..1.126 rows=325 loops=1)
                    Hash Cond: (l.zona_id = z.zona_id)
                    ->  Seq Scan on lokacija l  (cost=0.00..56.00 rows=3000 width=20) (actual time=0.007..0.231 rows=3000 loops=1)
                    ->  Hash  (cost=86.50..86.50 rows=325 width=19) (actual time=0.416..0.416 rows=325 loops=1)
                          Buckets: 1024  Batches: 1  Memory Usage: 25kB
                          ->  Seq Scan on zona z  (cost=0.00..86.50 rows=325 width=19) (actual time=0.008..0.357 rows=325 loops=1)
                                Filter: ((ime)::text = 'uchilishna zona'::text)
                                Rows Removed by Filter: 2675
  ->  Memoize  (cost=0.15..0.19 rows=1 width=222) (actual time=0.001..0.001 rows=1 loops=34)
        Cache Key: k.tip_kamera_id
        Cache Mode: logical
        Hits: 32  Misses: 2  Evictions: 0  Overflows: 0  Memory Usage: 1kB
        ->  Index Scan using tipkamera_pkey on tipkamera tk  (cost=0.14..0.18 rows=1 width=222) (actual time=0.007..0.007 rows=1 loops=2)
              Index Cond: (tip_kamera_id = k.tip_kamera_id)
Planning Time: 0.476 ms
Execution Time: 2.689 ms

Анализа на View7: Активни жалби

Прашалниците кои ќе ги тестираме се следните:

-- 7A: приказ на активни жалби според статус
SELECT *
FROM vw_aktivni_zalbi
WHERE status = 'podnesena';

-- 7B: анализа на планот на извршување за активни жалби според статус
EXPLAIN ANALYZE
SELECT *
FROM vw_aktivni_zalbi
WHERE status = 'podnesena';
  1. Примарен филтер за погледот vw_aktivni_zalbi ќе биде според status. Погледот ќе се користи за брз преглед на жалби кои се во тек на обработка.
  1. Примарен случај на употреба ќе биде следење на активните жалби и нивната моментална состојба. За овој поглед перформансите се важни бидејќи се поврзуваат табелите Zalba, Korisnik, Gragjanin и Prekrsok.

Време на извршување без индекси

7A - 34068 ms

При извршување на прашалникот:

SELECT *
FROM vw_aktivni_zalbi
WHERE status = 'podnesena';

Прашалникот успешно ги прикажува сите активни жалби со статус podnesena, заедно со информациите за прекршокот и граѓанинот кој ја поднел жалбата.

При извршување на прашалникот, DataGrip прикажува време на извршување од 34068 ms, односно приближно 34 секунди.

Поради големиот број записи и поврзувањето на повеќе табели, времето на извршување е значително поголемо од поставениот праг.

7B - 87924 ms

Gather  (cost=1001.28..165958.95 rows=17682 width=178) (actual time=48.482..87720.979 rows=1751073 loops=1)
  Workers Planned: 4
  Workers Launched: 4
  ->  Nested Loop Left Join  (cost=1.28..163190.75 rows=4420 width=178) (actual time=51.788..87379.859 rows=350215 loops=5)
        ->  Nested Loop Left Join  (cost=0.85..134440.88 rows=4420 width=95) (actual time=51.697..85565.365 rows=350215 loops=5)
              ->  Nested Loop Left Join  (cost=0.43..131622.48 rows=4420 width=67) (actual time=41.937..54618.455 rows=350215 loops=5)
                    ->  Parallel Seq Scan on zalba z  (cost=0.00..112180.56 rows=4420 width=57) (actual time=15.090..524.515 rows=350215 loops=5)
"                          Filter: (((status)::text = 'podnesena'::text) AND (lower((status)::text) = ANY ('{podnesena,vo_postapka}'::text[])))"
                          Rows Removed by Filter: 1049785
                    ->  Index Scan using korisnik_pkey on korisnik k  (cost=0.43..4.40 rows=1 width=18) (actual time=0.154..0.154 rows=1 loops=1751073)
                          Index Cond: (korisnik_id = z.korisnik_id)
              ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..0.64 rows=1 width=42) (actual time=0.088..0.088 rows=1 loops=1751073)
                    Index Cond: (embg = (k.embg)::bpchar)
        ->  Index Scan using prekrsok_pkey on prekrsok p  (cost=0.43..6.50 rows=1 width=87) (actual time=0.005..0.005 rows=1 loops=1751073)
              Index Cond: (prekrsok_id = z.prekrsok_id)
Planning Time: 0.833 ms
JIT:
  Functions: 90
"  Options: Inlining false, Optimization false, Expressions true, Deforming true"
"  Timing: Generation 7.367 ms (Deform 3.709 ms), Inlining 0.000 ms, Optimization 3.573 ms, Emission 71.609 ms, Total 82.549 ms"
Execution Time: 87808.602 ms

Креирани индекси за оптимизација:

CREATE INDEX idx_zalba_status
ON Zalba(status);

CREATE INDEX idx_zalba_korisnik_id
ON Zalba(korisnik_id);

CREATE INDEX idx_zalba_prekrsok_id
ON Zalba(prekrsok_id);

Индексот idx_zalba_status се користи за побрзо филтрирање на жалбите според статус. Индексите idx_zalba_korisnik_id и idx_zalba_prekrsok_id се додаваат бидејќи табелата Zalba се поврзува со Korisnik и Prekrsok преку овие колони.

Време на извршување со индекси

7A - 2044 ms (беше 34068 ms)

При повторно извршување на прашалникот по креирање на индексите, времето на извршување се намали од 34 секунди на околу 2 секунди.

7B - 9958.522 ms (беше 87808.602 ms)

Gather  (cost=1001.28..165947.35 rows=17682 width=178) (actual time=13.649..9870.867 rows=1751073 loops=1)
  Workers Planned: 4
  Workers Launched: 4
  ->  Nested Loop Left Join  (cost=1.28..163179.15 rows=4420 width=178) (actual time=15.231..9086.458 rows=350215 loops=5)
        ->  Nested Loop Left Join  (cost=0.85..134440.33 rows=4420 width=95) (actual time=15.136..7178.456 rows=350215 loops=5)
              ->  Nested Loop Left Join  (cost=0.43..131621.92 rows=4420 width=67) (actual time=15.025..2527.731 rows=350215 loops=5)
                    ->  Parallel Seq Scan on zalba z  (cost=0.00..112180.00 rows=4420 width=57) (actual time=14.877..530.185 rows=350215 loops=5)
"                          Filter: (((status)::text = 'podnesena'::text) AND (lower((status)::text) = ANY ('{podnesena,vo_postapka}'::text[])))"
                          Rows Removed by Filter: 1049785
                    ->  Index Scan using korisnik_pkey on korisnik k  (cost=0.43..4.40 rows=1 width=18) (actual time=0.005..0.005 rows=1 loops=1751073)
                          Index Cond: (korisnik_id = z.korisnik_id)
              ->  Index Scan using gragjanin_pkey on gragjanin g  (cost=0.43..0.64 rows=1 width=42) (actual time=0.013..0.013 rows=1 loops=1751073)
                    Index Cond: (embg = (k.embg)::bpchar)
        ->  Index Scan using prekrsok_pkey on prekrsok p  (cost=0.42..6.50 rows=1 width=87) (actual time=0.005..0.005 rows=1 loops=1751073)
              Index Cond: (prekrsok_id = z.prekrsok_id)
Planning Time: 1.002 ms
JIT:
  Functions: 90
"  Options: Inlining false, Optimization false, Expressions true, Deforming true"
"  Timing: Generation 7.452 ms (Deform 3.796 ms), Inlining 0.000 ms, Optimization 3.529 ms, Emission 70.615 ms, Total 81.595 ms"
Execution Time: 9958.522 ms

По креирањето на индексите idx_zalba_status, idx_zalba_korisnik_id и idx_zalba_prekrsok_id, PostgreSQL може поефикасно да ги пронајде записите во табелата Zalba и да ги изврши спојувањата со табелите Korisnik и Prekrsok.

Времето на извршување на прашалникот се намали од 87808.602 ms на 9958.522 ms, што претставува подобрување од приближно 10 пати.

Анализа на View8: Зони со најмногу прекршоци

Прашалниците кои ќе ги тестираме се следните:

-- 8A: приказ на бројот на прекршоци за конкретна зона
SELECT *
FROM vw_zoni_so_najmnogu_prekrsoci
WHERE zona = 'bolnichka zona';

-- 8B: анализа на планот на извршување за конкретна зона
EXPLAIN ANALYZE
SELECT *
FROM vw_zoni_so_najmnogu_prekrsoci
WHERE zona = 'bolnichka zona';
  1. Примарен филтер за погледот vw_zoni_so_najmnogu_prekrsoci ќе биде според zona. Погледот ќе се користи за приказ на бројот на прекршоци во конкретна зона.
  1. Примарен случај на употреба ќе биде анализа на зони со најголем број прекршоци. За овој поглед перформансите се важни бидејќи се поврзуваат табелите Zona, Lokacija, Kamera и Prekrsok, а потоа се врши групирање со COUNT.

Време на извршување без индекси

8A - 584 ms

При извршување на прашалникот:

SELECT *
FROM vw_zoni_so_najmnogu_prekrsoci
WHERE zona = 'bolnichka zona';

Прашалникот успешно го прикажува бројот на прекршоци за зоната bolnichka zona.

При извршување на прашалникот, DataGrip прикажува време на извршување од 584 ms.

8B - 566 ms

HashAggregate  (cost=98630.18..98632.83 rows=265 width=27) (actual time=491.600..491.651 rows=265 loops=1)
  Group Key: z.zona_id
  Batches: 1  Memory Usage: 61kB
  ->  Hash Right Join  (cost=224.22..97936.46 rows=138743 width=23) (actual time=1.901..473.067 rows=88342 loops=1)
        Hash Cond: (p.kamera_id = k.kamera_id)
        ->  Seq Scan on prekrsok p  (cost=0.00..90434.77 rows=1570677 width=8) (actual time=0.012..301.843 rows=1000010 loops=1)
        ->  Hash  (cost=220.91..220.91 rows=265 width=23) (actual time=1.875..1.881 rows=265 loops=1)
              Buckets: 1024  Batches: 1  Memory Usage: 23kB
              ->  Hash Right Join  (cost=157.01..220.91 rows=265 width=23) (actual time=1.203..1.827 rows=265 loops=1)
                    Hash Cond: (k.lokacija_id = l.lokacija_id)
                    ->  Seq Scan on kamera k  (cost=0.00..50.00 rows=3000 width=8) (actual time=0.009..0.220 rows=3000 loops=1)
                    ->  Hash  (cost=153.70..153.70 rows=265 width=23) (actual time=1.185..1.189 rows=265 loops=1)
                          Buckets: 1024  Batches: 1  Memory Usage: 23kB
                          ->  Hash Right Join  (cost=89.81..153.70 rows=265 width=23) (actual time=0.477..1.133 rows=265 loops=1)
                                Hash Cond: (l.zona_id = z.zona_id)
                                ->  Seq Scan on lokacija l  (cost=0.00..56.00 rows=3000 width=8) (actual time=0.009..0.232 rows=3000 loops=1)
                                ->  Hash  (cost=86.50..86.50 rows=265 width=19) (actual time=0.441..0.442 rows=265 loops=1)
                                      Buckets: 1024  Batches: 1  Memory Usage: 22kB
                                      ->  Seq Scan on zona z  (cost=0.00..86.50 rows=265 width=19) (actual time=0.036..0.391 rows=265 loops=1)
                                            Filter: ((ime)::text = 'bolnichka zona'::text)
                                            Rows Removed by Filter: 2735
Planning Time: 0.561 ms
Execution Time: 491.742 ms

Анализа на View9: Локации со најмногу жалби

Прашалниците кои ќе ги тестираме се следните:

-- 9A: приказ на бројот на жалби за конкретна зона
SELECT *
FROM vw_lokacii_so_najmnogu_zalbi
WHERE lokacija_id = 15;

-- 9B: анализа на планот на извршување за конкретна зона
EXPLAIN ANALYZE
SELECT *
FROM vw_lokacii_so_najmnogu_zalbi
WHERE lokacija_id = 15;
  1. Примарен филтер за погледот vw_lokacii_so_najmnogu_zalbi ќе биде според zona. Погледот ќе се користи за приказ на локации со најголем број поднесени жалби во одредена зона.
  1. Примарен случај на употреба ќе биде анализа на локации каде што граѓаните најчесто поднесуваат жалби. За овој поглед перформансите се важни бидејќи се поврзуваат табелите Lokacija, Zona, Kamera, Prekrsok и Zalba, а потоа се врши групирање со COUNT.

Време на извршување без индекси

9A - 1974 ms

При извршување на прашалникот:

SELECT *
FROM vw_lokacii_so_najmnogu_zalbi
WHERE lokacija_id = 15;

Прашалникот успешно го прикажува бројот на жалби за локацијата со идентификатор 15.

При извршување на прашалникот, DataGrip прикажува време на извршување од 1974 ms, односно приближно 2 секунди.

9B - 2474 ms

GroupAggregate  (cost=272610.26..272627.87 rows=10 width=39) (actual time=2406.148..2406.157 rows=1 loops=1)
  Group Key: z.ime
  ->  Sort  (cost=272610.26..272616.10 rows=2335 width=35) (actual time=2405.597..2405.740 rows=2364 loops=1)
        Sort Key: z.ime
        Sort Method: quicksort  Memory: 226kB
        ->  Hash Right Join  (cost=94649.53..272479.63 rows=2335 width=35) (actual time=496.478..2403.630 rows=2364 loops=1)
              Hash Cond: (zl.prekrsok_id = p.prekrsok_id)
              ->  Seq Scan on zalba zl  (cost=0.00..151556.27 rows=7000127 width=8) (actual time=0.036..795.482 rows=7000000 loops=1)
              ->  Hash  (cost=94642.98..94642.98 rows=524 width=35) (actual time=496.302..496.309 rows=334 loops=1)
                    Buckets: 1024  Batches: 1  Memory Usage: 31kB
                    ->  Nested Loop Left Join  (cost=58.07..94642.98 rows=524 width=35) (actual time=26.370..496.059 rows=334 loops=1)
                          ->  Nested Loop Left Join  (cost=0.56..16.60 rows=1 width=31) (actual time=25.803..25.811 rows=1 loops=1)
                                ->  Index Scan using lokacija_pkey on lokacija l  (cost=0.28..8.30 rows=1 width=20) (actual time=0.015..0.021 rows=1 loops=1)
                                      Index Cond: (lokacija_id = 15)
                                ->  Index Scan using zona_pkey on zona z  (cost=0.28..8.30 rows=1 width=19) (actual time=0.023..0.024 rows=1 loops=1)
                                      Index Cond: (zona_id = l.zona_id)
                          ->  Hash Right Join  (cost=57.51..94621.14 rows=524 width=8) (actual time=0.560..470.129 rows=334 loops=1)
                                Hash Cond: (p.kamera_id = k.kamera_id)
                                ->  Seq Scan on prekrsok p  (cost=0.00..90434.77 rows=1570677 width=8) (actual time=0.011..303.832 rows=1000010 loops=1)
                                ->  Hash  (cost=57.50..57.50 rows=1 width=8) (actual time=0.277..0.279 rows=1 loops=1)
                                      Buckets: 1024  Batches: 1  Memory Usage: 9kB
                                      ->  Seq Scan on kamera k  (cost=0.00..57.50 rows=1 width=8) (actual time=0.026..0.269 rows=1 loops=1)
                                            Filter: (lokacija_id = 15)
                                            Rows Removed by Filter: 2999
Planning Time: 0.682 ms
JIT:
  Functions: 36
"  Options: Inlining false, Optimization false, Expressions true, Deforming true"
"  Timing: Generation 2.019 ms (Deform 1.148 ms), Inlining 0.000 ms, Optimization 1.004 ms, Emission 24.890 ms, Total 27.912 ms"
Execution Time: 2408.367 ms
Note: See TracWiki for help on using the wiki.