wiki:Monitoring

Version 1 (modified by 213192, 3 weeks ago) ( diff )

--

Мониторинг

Query Latency Distribution

Просечниот execution time не ја претставува реалната состојба во системот. На пример 990 прашалници имаат време на извршување 1мс, додека 10 имаат 5000мс. Просекот е 50мс, но може да видиме дека тие 10 прашалници се outliers. Токму овие 10 спори прашалници можат да го нарушат корисничкото искуство.

Пример за брз прашалник:

SELECT * FROM players WHERE player_id = 10;

Пример за спор прашалник:

SELECT 
    p.player_name,
    COUNT(t.transfer_id),
    AVG(t.transfer_fee),
    SUM(m.attendance)
FROM players p
JOIN transfers t ON p.player_id = t.player_id
JOIN matches m ON m.home_team_id = p.club_id 
              OR m.away_team_id = p.club_id
GROUP BY p.player_name;

Исто така, имаме два типа на прашалници: еден што има 10000 повици на ден со време на извршување 2мс и друг со 50 повици на ден со 5 секунди време на извршување. Вториот прашалник претставува поголем проблем за нашиот систем бидејќи корисникот не сака да чека slow response.

Hot Data vs Cold Data Monitoring

Како што веќе видовме, системот располага со повеќе табели. Некои од нив се користат повеќе од останатите и може да се каже дека во реален систем 20% од податоците генерираат 80% од оптоварувањето.

Класичен пример може да најдеме во табелата players. Од сите играчи кои се во табелата, најинтересни се познатите играчи - топ играчи. Токму затоа овие играчи ќе се најдат во повеќе прашалници од останати играчи и ќе се создаде row-level contention. Мониторинг резултат од гореспоменатиот проблем е тоа што играчот со id 10 ќе има 1200 queries/min, додека тој со id 187 ќе има 5 queries/min. Истите сценарија можат да се најдат и во други табели.

Од друга страна, имаме и cold data која ретко се користи, нема locks и contention.

Пример

Во Transfermarkt системот, „deadline day“ претставува екстремен случај на оптоварување, при што во краток временски интервал се извршуваат илјадници трансфер операции. За разлика од нормалниот режим, каде системот е претежно read-oriented, во овој период се јавува нагло зголемување на write операции и конкурентни трансакции.

Во наредните примери ќе видиме и зашто ова е едно од најпредизивикувачките сценарија во системот.

  1. Complex Transfer Transaction

Секој трансфер не е едноставен INSERT, туку составена трансакција:

BEGIN;

INSERT INTO transfers(player_id, from_club_id, to_club_id, transfer_fee, season)
VALUES (25, 3, 8, 12000000, '2025');

UPDATE players
SET market_value = market_value + 1500000,
    club_id = 8
WHERE player_id = 25;

UPDATE clubs
SET budget = budget - 12000000
WHERE club_id = 8;

UPDATE clubs
SET budget = budget + 12000000
WHERE club_id = 3;

COMMIT;

Може да видиме дека имаме 4 write операции во 3 различни табели и сето ова е само за еден играч, додека на deadline day имаме илјадници трансфери. Исто така, системот влегува во contention режим поради тоа што сите трансакции таргетираат исти ентитети (player_id = 25, club_id = 8) и latency и queries/sec се зголемуваат драстично. Уште еден проблем со кој се соочуваме е transaction queueing, а тоа се случува бидејќи трансакцијата која се извршува зад себе остава други трансакции кои чекаат ресурси. Овој проблем е чест и во нормални услови, но на deadline day е многу посериозен.

Спојување на две табели во една

Во последниот пример ќе направиме денормализација на системот, односно табелите players и player_valuations ќе ги споиме во една и ќе споредиме што е подобро.

SELECT
p.last_name,
pv.market_value_in_eur,
pv.date
FROM players p
JOIN player_valuations pv
ON p.player_id = pv.player_id
WHERE p.player_id = 10
ORDER BY pv.date DESC
LIMIT 1;

Ова query има JOIN и ORDER BY + LIMIT.

CREATE TABLE players_with_value AS
SELECT
p.player_id,
p.last_name,
p.current_club_id,
pv.market_value_in_eur,
pv.date
FROM players p
JOIN player_valuations pv
ON p.player_id = pv.player_id;
SELECT last_name, market_value_in_eur
FROM players_with_value
WHERE player_id = 10
ORDER BY date DESC
LIMIT 1;

Користејќи ја новокреираната табела извршивме query кој не користи JOIN и има побрз пристап. Сепак, целосна денормализација не е најдоброто решение. За најдобри резултати во нашиот систем ќе искористиме partial denormalization, односно ќе направиме нова табела со моменталната/последната вредност на играчот:

CREATE TABLE players_current_value AS
SELECT DISTINCT ON (player_id)
player_id,
market_value,
date
FROM player_valuations
ORDER BY player_id, date DESC;

Предности што ги добиваме со ова се тоа што нема непотребно скенирање на целата историја доколку корисникот не ја бара, помалку write операции и помал contention.

Note: See TracWiki for help on using the wiki.