Changes between Initial Version and Version 1 of Phase4_Performance_Analysis


Ignore:
Timestamp:
05/09/26 19:44:37 (2 weeks ago)
Author:
226052
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Phase4_Performance_Analysis

    v1 v1  
     1= Мерење на перформанси
     2
     3Извршена е анализа на перформансите на базата film_rental во PostgreSQL. Се споредуваат неоптимизирани табели и оптимизирани табели:
     4* rental_copy - непартиционирана табела, користена како почетна состојба за споредба;
     5* rental - партиционирана табела според rental_date, со дополнителни индекси;
     6* payment_copy - непартиционирана табела за плаќања;
     7* payment - партиционирана табела според payment_date, со индекс за датум и вработен.
     8За оваа анализа беше користено pgbench. Секој тест се извршува со повеќе паралелни клиенти, при што се мерат просечна латентност и TPS, односно број на трансакции во секунда. Во сите тестови бројот на неуспешни трансакции беше 0.
     9
     10
     11Пример за извршување на benchmark тест:
     12
     13pgbench -n -U admin -d film_rental -c 10 -j 2 -T 60 -f /tmp/movie_recommendation_rental_copy.sql
     14
     15Каде:
     16-n означува дека pgbench не ја иницијализира стандардната pgbench шема;
     17-U admin е корисникот со кој се поврзува кон базата;
     18-d film_rental е базата врз која се извршува тестот;
     19-c 10 означува 10 паралелни клиенти;
     20-j 2 означува 2 работни нишки;
     21-T 60 означува времетраење од 60 секунди;
     22-f ја задава SQL датотеката што се извршува.
     23
     24Истата команда се повторуваше со различен број клиенти, на пример 10, 20, 30 и 50, и со SQL датотеки за неоптимизираната и оптимизираната верзија.
     25
     26== Детални резултати
     27
     28=== Q1 - Movie Recommendation
     29Прашалникот прави препорака на филмови за конкретен корисник. Се анализираат претходните изнајмувања, омилените категории, рејтинзите и популарноста на филмовите во 2024 година.
     30
     31{{{
     32WITH customer_history AS (
     33    SELECT DISTINCT
     34        f.film_id,
     35        f.rating,
     36        fc.category_id
     37    FROM rental_copy r
     38    JOIN inventory i ON r.inventory_id = i.inventory_id
     39    JOIN film f ON i.film_id = f.film_id
     40    JOIN film_category fc ON f.film_id = fc.film_id
     41    WHERE r.customer_id = 101
     42),
     43preferred_categories AS (
     44    SELECT
     45        category_id,
     46        COUNT(*) AS category_score
     47    FROM customer_history
     48    GROUP BY category_id
     49),
     50candidate_films AS (
     51    SELECT
     52        f.film_id,
     53        f.title,
     54        f.rating,
     55        fc.category_id,
     56        pc.category_score
     57    FROM film f
     58    JOIN film_category fc ON f.film_id = fc.film_id
     59    JOIN preferred_categories pc ON fc.category_id = pc.category_id
     60    WHERE NOT EXISTS (
     61        SELECT 1
     62        FROM customer_history ch
     63        WHERE ch.film_id = f.film_id
     64    )
     65),
     66film_popularity AS (
     67    SELECT
     68        i.film_id,
     69        COUNT(r.rental_id) AS rental_count
     70    FROM rental_copy r
     71    JOIN inventory i ON r.inventory_id = i.inventory_id
     72    WHERE r.rental_date >= DATE '2024-01-01'
     73      AND r.rental_date < DATE '2025-01-01'
     74    GROUP BY i.film_id
     75)
     76SELECT
     77    cf.film_id,
     78    cf.title,
     79    cf.rating,
     80    c.name AS category,
     81    cf.category_score,
     82    COALESCE(fp.rental_count, 0) AS yearly_rentals,
     83    (cf.category_score * 10 + COALESCE(fp.rental_count, 0)) AS recommendation_score
     84FROM candidate_films cf
     85JOIN category c ON cf.category_id = c.category_id
     86LEFT JOIN film_popularity fp ON cf.film_id = fp.film_id
     87WHERE cf.rating IN (
     88    SELECT rating
     89    FROM customer_history
     90)
     91ORDER BY recommendation_score DESC, cf.title
     92LIMIT 10;
     93}}}
     94
     95За оптимизираната верзија се користи истата логика, но наместо rental_copy се користи партиционираната табела rental.
     96
     97|| '''Clients''' || '''Threads''' || '''rental_copy latency''' || '''rental_copy TPS''' || '''rental latency''' || '''rental TPS''' ||
     98|| 10            || 2             || 2235.603 ms               || 4.473                 || 1083.428 ms          || 9.230            ||
     99|| 20            || 4             || 4036.198 ms               || 4.955                 || 2208.459 ms          || 9.056            ||
     100|| 50            || 4             || 9487.494 ms               || 5.270                 || 5247.761 ms          || 9.528            ||
     101
     102Q1 покажува значително подобрување кај оптимизираната табела. Кај 10 клиенти латентноста е намалена за околу 51.5%, а TPS е зголемен за околу 106.3%. Кај 50 клиенти латентноста е намалена за околу 44.7%, а TPS е зголемен за околу 80.8%. Ова се случува бидејќи прашалникот користи customer_id, inventory_id и rental_date. Индексите помагаат при пребарување на историјата на корисникот, а партиционирањето помага при делот од прашалникот кој ја пресметува популарноста за 2024 година.
     103
     104=== Q2 - Popular Films 2024
     105Прашалникот ги пресметува најизнајмуваните филмови во 2024 година. Се користи филтер по датум, спојување со inventory и film, групирање по филм и сортирање според бројот на изнајмувања.
     106{{{
     107SELECT
     108    f.film_id,
     109    f.title,
     110    f.rating,
     111    COUNT(r.rental_id) AS rental_count
     112FROM rental_copy r
     113JOIN inventory i ON r.inventory_id = i.inventory_id
     114JOIN film f ON i.film_id = f.film_id
     115WHERE r.rental_date >= DATE '2024-01-01'
     116  AND r.rental_date < DATE '2025-01-01'
     117GROUP BY f.film_id, f.title, f.rating
     118ORDER BY rental_count DESC
     119LIMIT 20;
     120}}}
     121
     122За оптимизираната верзија се користи истата логика, но наместо rental_copy се користи партиционираната табела rental.
     123
     124|| '''Clients''' || '''rental_copy latency''' || '''rental_copy TPS''' || '''rental latency''' || '''rental TPS''' || '''Промена''' ||
     125|| 10 || 2222.438 ms || 4.500 || 1628.696 ms || 6.140 || ~26.7% побрзо ||
     126|| 20 || 4205.239 ms || 4.756 || 3828.958 ms || 5.223 || ~8.9% побрзо ||
     127|| 30 || 6545.865 ms || 4.583 || 6648.265 ms || 4.512 || ~1.6% побавно ||
     128|| 50 || 11077.453 ms || 4.514 || 11290.484 ms || 4.429 || ~1.9% побавно ||
     129
     130Q2 има мешани резултати. Кај 10 и 20 клиенти партиционираната табела е побрза, но кај 30 и 50 клиенти резултатот е речиси ист или малку полош.
     131Ова покажува дека партиционирањето не секогаш гарантира подобрување. Кај овој прашалник, освен читање од rental, има и GROUP BY, ORDER BY и LIMIT. При поголем број паралелни клиенти главен трошок може да станат агрегацијата и сортирањето, а не само читањето на редови од табелата.
     132
     133
     134Q3 - Monthly Revenue
     135Прашалникот пресметува месечен приход по продавница за 2024 година. Се пресметуваат број на плаќања, вкупен приход, просечна, минимална и максимална уплата.
     136
     137{{{
     138SELECT
     139    date_trunc('month', p.payment_date) AS month,
     140    s.store_id,
     141    COUNT(p.payment_id) AS payments_count,
     142    SUM(p.amount) AS total_revenue,
     143    AVG(p.amount) AS avg_payment,
     144    MIN(p.amount) AS min_payment,
     145    MAX(p.amount) AS max_payment
     146FROM payment_copy p
     147JOIN staff s ON p.staff_id = s.staff_id
     148WHERE p.payment_date >= DATE '2024-01-01'
     149  AND p.payment_date < DATE '2025-01-01'
     150GROUP BY date_trunc('month', p.payment_date), s.store_id
     151ORDER BY month, s.store_id;
     152}}}
     153
     154За оптимизираната верзија се користи истата логика, но наместо payment_copy се користи партиционираната табела payment.
     155
     156|| '''Clients''' || '''payment_copy latency''' || '''payment_copy TPS''' || '''payment latency''' || '''payment TPS''' || '''Промена''' ||
     157|| 10 || 2627.300 ms || 3.806 || 1055.953 ms || 9.470 || ~59.8% побрзо ||
     158|| 30 || 8545.741 ms || 3.511 || 3325.437 ms || 9.021 || ~61.1% побрзо ||
     159|| 50 || 16138.221 ms || 3.098 || 5321.565 ms || 9.396 || ~67.0% побрзо ||
     160
     161Q3 покажува најстабилно подобрување кај аналитичките прашалници. Прашалникот пресметува месечен приход по продавница за 2024 година, а табелата payment е партиционирана според payment_date. Бидејќи условот користи временски интервал за 2024 година, PostgreSQL може да ја чита партицијата за 2024 година наместо целата табела. Затоа латентноста е намалена за околу 60-67%, а TPS е зголемен за околу 149-203%.
     162
     163=== Q4 - INSERT rental
     164
     165Овој тест мери внесување нови редови во табелата за изнајмувања. За benchmark редовите се користи посебен датум 2026-03-07 12:00:00, за да се разликуваат од оригиналните податоци.
     166
     167{{{
     168INSERT INTO rental_copy (rental_date, inventory_id, customer_id, staff_id)
     169VALUES (
     170    TIMESTAMP '2026-03-07 12:00:00',
     171    floor(random() * 50000 + 1)::int,
     172    floor(random() * 1000000 + 1)::int,
     173    floor(random() * 50 + 1)::int
     174);
     175}}}
     176
     177За оптимизираната верзија се користи истата логика, но внесувањето се прави во партиционираната табела rental.
     178
     179|| '''Clients''' || '''rental_copy latency''' || '''rental_copy TPS''' || '''rental latency''' || '''rental TPS''' || '''Промена''' ||
     180|| 10 || 3.121 ms || 3204.533 || 2.855 ms || 3502.623 || ~8.5% побрзо ||
     181|| 30 || 2.949 ms || 10173.818 || 3.147 ms || 9533.949 || ~6.7% побавно ||
     182|| 50 || 6.756 ms || 7400.777 || 3.088 ms || 16190.222 || ~54.3% побрзо ||
     183
     184INSERT операциите имаат мешани резултати. Кај 10 и 50 клиенти партиционираната табела е побрза, но кај 30 клиенти непартиционираната табела има малку подобар резултат.
     185Причината е тоа што при внесување PostgreSQL мора да одреди во која партиција припаѓа новиот ред и мора да ги ажурира индексите. Тоа додава мал overhead, но при поголемо конкурентно оптоварување партиционираната структура може да помогне затоа што записите се насочуваат кон конкретна партиција.
     186
     187=== Q5 - UPDATE rental
     188Овој тест мери ажурирање на изнајмувања. Се избира еден ред со benchmark датумот и со return_date IS NULL, па потоа се поставува return_date = now().
     189{{{
     190UPDATE rental_copy
     191SET return_date = now()
     192WHERE rental_id = (
     193    SELECT rental_id
     194    FROM rental_copy
     195    WHERE rental_date = TIMESTAMP '2026-03-07 12:00:00'
     196      AND return_date IS NULL
     197    LIMIT 1
     198);
     199}}}
     200
     201За оптимизираната верзија се користи истата логика, но ажурирањето се прави врз партиционираната табела rental.
     202
     203|| '''Clients''' || '''rental_copy latency''' || '''rental_copy TPS''' || '''rental latency''' || '''rental TPS''' || '''Промена''' ||
     204|| 10 || 590.026 ms || 16.948 || 7.044 ms || 1419.709 || ~98.8% побрзо ||
     205|| 30 || 1483.097 ms || 20.228 || 12.318 ms || 2435.437 || ~99.2% побрзо ||
     206|| 50 || 2646.029 ms || 18.896 || 16.689 ms || 2996.003 || ~99.4% побрзо ||
     207
     208UPDATE операцијата покажува најголемо подобрување. Условот користи конкретен rental_date, па кај партиционираната табела PostgreSQL може да пребарува само во релевантната партиција. Кај rental_copy системот мора да пребарува низ голема непартиционирана табела. Затоа латентноста е многу поголема, а TPS е многу помал.
     209
     210== Вкупно подобрување
     211Партиционираните табели и индексите покажуваат значително подобрување кај прашалници кои се временски ограничени и кај операции кои можат да се насочат кон конкретна партиција.
     212Најголеми придобивки:
     213
     214* Q3 - Monthly Revenue: околу 64.5% просечно намалување на латентноста.
     215* Q5 - UPDATE rental: околу 99.2% просечно намалување на латентноста.
     216* Q1 - Movie Recommendation: околу 45.8% просечно намалување на латентноста.
     217
     218Мешани резултати:
     219* Q2 - Popular Films има подобрување кај 10 и 20 клиенти, но мало влошување кај 30 и 50 клиенти.
     220* Q4 - INSERT има подобрување кај 10 и 50 клиенти, но мало влошување кај 30 клиенти.
     221
     222Ова покажува дека оптимизацијата мора да се мери. Партиционирањето не е автоматско решение за сите прашалници. Најмногу помага кога WHERE условот ја користи колоната по која е направено партиционирањето.
     223
     224== Операции на читање со мешани резултати
     225
     226* Q1 - Movie Recommendation: јасно подобрување кај сите нивоа на конкурентност.
     227* Q2 - Popular Films: подобро кај помал број клиенти, но речиси исто или малку полошо кај поголем број клиенти.
     228* Q3 - Monthly Revenue: најдобар пример каде партиционирањето директно го намалува бројот на редови што треба да се читаат.
     229
     230Кај читањата кои содржат големи агрегации и сортирања, како Q2, главниот проблем не е секогаш табелата од која се чита. Понекогаш главниот трошок е обработката по читањето, односно GROUP BY и ORDER BY.
     231
     232== Операции на запишување
     233
     234* INSERT: просечно подобрување, но со варијации.
     235* UPDATE: многу големо подобрување поради филтрирање по rental_date.
     236
     237Кај INSERT, партиционирањето може да додаде overhead затоа што секој ред мора да се насочи во соодветна партиција. Кај UPDATE, партиционирањето е многу корисно кога условот ја користи партициската колона, бидејќи пребарувањето се ограничува на мала партиција наместо на целата табела.
     238
     239== Заклучок
     240За ова специфично работно оптоварување:
     241
     242* Партиционирањето е многу корисно за временски извештаи, особено кај payment и rental.
     243* Индексите значително помагаат кај прашалници со WHERE услови и JOIN операции врз често користени колони.
     244* Q3 и Q5 покажуваат најголемо подобрување, затоа што директно ја користат колоната по која е направено партиционирањето.
     245* Q2 покажува дека партиционирањето не го решава секој проблем, бидејќи агрегацијата и сортирањето можат да станат главен bottleneck.
     246* INSERT операциите треба да се мерат внимателно, бидејќи партиционирањето и индексите можат да додадат мал overhead.
     247
     248Најсоодветен пристап за оваа база е да се задржи партиционирањето по датум за големите трансакциски табели rental и payment, да се користат индекси само за најчестите филтри и спојувања, и редовно да се проверуваат резултатите со EXPLAIN ANALYZE и pgbench.
     249
     250
     251
     252
     253
     254
     255
     256
     257
     258
     259
     260
     261
     262
     263
     264
     265
     266
     267
     268
     269
     270
     271