Changes between Version 8 and Version 9 of otherdevelopment


Ignore:
Timestamp:
06/12/26 18:32:51 (3 days ago)
Author:
233062
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • otherdevelopment

    v8 v9  
    33== Анализа на перформанси ==
    44
     5=== Извештај за годишна тренинг активност на корисници ===
     6
     7Анализата на перформанси се врши врз основа на моменталната состојба во базата, која има податоци кои служат за тестирање. Базата содржи: ~1000 корисници, ~1000 тренинг сесии (training_sessions), ~900 тренинг профили.
     8
     9SQL:
     10
     11{{{
     12CREATE OR REPLACE FUNCTION test_training_report()
     13RETURNS void AS $$
     14DECLARE
     15  start_time timestamptz;
     16  end_time   timestamptz;
     17  duration   int;
     18BEGIN
     19  start_time := clock_timestamp();
     20
     21  PERFORM *
     22  FROM (
     23      WITH params AS (SELECT 2026::int AS report_year),
     24      months AS (SELECT generate_series(1,12) AS month_no),
     25      training_base AS (
     26          SELECT tu.user_id FROM training_users tu
     27      ),
     28      monthly_sessions AS (
     29          SELECT
     30              tb.user_id,
     31              m.month_no,
     32              COUNT(ts.training_id)            AS sessions_count,
     33              COALESCE(SUM(ts.duration), 0)    AS total_duration_minutes,
     34              COALESCE(SUM(ts.calories), 0)    AS total_calories
     35          FROM training_base tb
     36          CROSS JOIN months m
     37          LEFT JOIN training_sessions ts
     38              ON ts.training_user_id = tb.user_id
     39             AND EXTRACT(YEAR  FROM ts.date)::int = (SELECT report_year FROM params)
     40             AND EXTRACT(MONTH FROM ts.date)::int = m.month_no
     41          GROUP BY tb.user_id, m.month_no
     42      )
     43      SELECT user_id, SUM(sessions_count), SUM(total_calories)
     44      FROM monthly_sessions
     45      GROUP BY user_id
     46  ) t;
     47
     48  end_time := clock_timestamp();
     49  duration := round(1000 * (extract(epoch FROM end_time) - extract(epoch FROM start_time)));
     50
     51  RAISE NOTICE 'Query executed in: % ms', duration;
     52END;
     53$$ LANGUAGE plpgsql;
     54}}}
     55
     56Индекси:
     57
     581.
     59
     60{{{
     61CREATE INDEX idx_training_sessions_user_date
     62    ON training_sessions(training_user_id, date);
     63}}}
     64
     65Подобрување:
     66Index Scan наместо Seq Scan при LEFT JOIN по training_user_id + филтрирање по датум
     67
     682.
     69
     70{{{
     71CREATE INDEX idx_training_sessions_year
     72    ON training_sessions ((EXTRACT(YEAR FROM date)));
     73}}}
     74
     75Подобрување:
     76Избегнува full table scan за годишен филтер со expression index
     77
     783.
     79
     80{{{
     81CREATE INDEX idx_training_sessions_covering
     82    ON training_sessions(training_user_id, date, duration, calories);
     83}}}
     84
     85Подобрување:
     86Covering index — сите потребни колони за агрегатите (SUM duration, SUM calories, COUNT) се читаат директно од индексот без посета на heap страниците
     87
     88
     89== SQL за анализа на брзината ==
     90
     91{{{
     92CREATE OR REPLACE FUNCTION test_training_report()
     93RETURNS void AS $$
     94DECLARE
     95  start_time timestamptz;
     96  end_time   timestamptz;
     97  duration   int;
     98BEGIN
     99  start_time := clock_timestamp();
     100
     101  PERFORM *
     102  FROM (
     103      WITH params AS (SELECT 2026::int AS report_year),
     104      months AS (SELECT generate_series(1,12) AS month_no),
     105      training_base AS (
     106          SELECT tu.user_id FROM training_users tu
     107      ),
     108      monthly_sessions AS (
     109          SELECT
     110              tb.user_id,
     111              m.month_no,
     112              COUNT(ts.training_id)            AS sessions_count,
     113              COALESCE(SUM(ts.duration), 0)    AS total_duration_minutes,
     114              COALESCE(SUM(ts.calories), 0)    AS total_calories
     115          FROM training_base tb
     116          CROSS JOIN months m
     117          LEFT JOIN training_sessions ts
     118              ON ts.training_user_id = tb.user_id
     119             AND EXTRACT(YEAR  FROM ts.date)::int = (SELECT report_year FROM params)
     120             AND EXTRACT(MONTH FROM ts.date)::int = m.month_no
     121          GROUP BY tb.user_id, m.month_no
     122      )
     123      SELECT user_id, SUM(sessions_count), SUM(total_calories)
     124      FROM monthly_sessions
     125      GROUP BY user_id
     126  ) t;
     127
     128  end_time := clock_timestamp();
     129  duration := round(1000 * (extract(epoch FROM end_time) - extract(epoch FROM start_time)));
     130
     131  RAISE NOTICE 'Query executed in: % ms', duration;
     132END;
     133$$ LANGUAGE plpgsql;
     134
     135
     136-- 4. PERFORMANCE RUNS
     137-- run 1: no indexes
     138SELECT test_training_report();
     139
     140-- run 2: add idx_training_sessions_user_date
     141CREATE INDEX idx_training_sessions_user_date ON training_sessions(training_user_id, date);
     142ANALYZE training_sessions;
     143SELECT test_training_report();
     144
     145-- run 3: add idx_training_sessions_year (Expression Index)
     146CREATE INDEX idx_training_sessions_year ON training_sessions ((EXTRACT(YEAR FROM date)));
     147ANALYZE training_sessions;
     148SELECT test_training_report();
     149
     150-- run 4: add covering index
     151CREATE INDEX idx_training_sessions_covering ON training_sessions(training_user_id, date, duration, calories);
     152ANALYZE training_sessions;
     153SELECT test_training_report();
     154
     155-- Cleanup
     156DROP FUNCTION test_training_report();
     157}}}
     158
     159Сумарно:
     160Без индекси: ~67ms
     161Со индекси: ~24ms
     162Забрзување: ~2.8x
    5163
    6164=== Извештај за годишна финансиска активност на корисници ===