Итак, я хочу улучшить время выполнения запроса, которое занимает около 90 мсек c, наихудший случай - около 150 мсек c. В основном мне нужно получить текущую (в этом сезоне) статистику для каждой команды НБА. Примерно так -> https://stats.nba.com/teams/traditional/?sort=W_PCT&dir=-1 кроме (MIN, BLKA, PFD).
Столбцы в таблице player_stats: id, идентификатор_игры, идентификатор_команды, идентификатор_противника, идентификатор_проигрывателя, минуты, fg, fga, fga, fgp, fg3, fg3a, fg3p, ft, fta, ftp, orb, drb, trb, ast, stl , blk, tov, pf, pts, plus_minus, сезон, плей-офф.
Столбцы в таблице команд: id, team_name, short_name, other_names, ссылка, конференция.
Столбцы в таблице игр: id , home_team_id, home_team_score, away_team_id, away_team_score, дата, плей-офф, сезон.
У меня есть индексы и, насколько я знаю, они работают должным образом. Извините, если это вопрос для начинающих, но я не такой опыт написания запросов к базе данных.
SELECT
t.name AS team_name,
CONCAT('/teams/', t.short_name) AS team_url,
hg.hg + ag.ag AS tot_games,
hg.home_game_wons + ag.away_game_wons AS games_won,
hg.home_game_losses + ag.away_game_losses AS games_loss,
ROUND(((hg.home_game_wons + ag.away_game_wons) / ROUND(hg.hg + ag.ag)) * 100, 2) AS w_l_p,
ROUND(SUM(ps.fg) / ROUND(hg.hg + ag.ag), 1) AS fg,
ROUND(SUM(ps.fga) / ROUND(hg.hg + ag.ag), 1) AS fga,
ROUND(avg(ps.fgp)::decimal * 100, 1) AS fgp,
ROUND(SUM(ps.fg3) / ROUND(hg.hg + ag.ag), 1) AS fg3,
ROUND(SUM(ps.fg3a) / ROUND(hg.hg + ag.ag), 1) AS fg3a,
ROUND(avg(ps.fg3p)::decimal *100,1) AS fg3p,
ROUND(SUM(ps.ft) / ROUND(hg.hg + ag.ag), 1) AS ft,
ROUND(SUM(ps.fta) / ROUND(hg.hg + ag.ag), 1) AS fta,
ROUND(avg(ps.ftp)::decimal * 100,1) AS ftp,
ROUND(SUM(ps.orb) / ROUND(hg.hg + ag.ag), 1) AS orb,
ROUND(SUM(ps.drb) / ROUND(hg.hg + ag.ag), 1) AS drb,
ROUND(SUM(ps.trb) / ROUND(hg.hg + ag.ag), 1) AS trb,
ROUND(SUM(ps.ast) / ROUND(hg.hg + ag.ag), 1) AS ast,
ROUND(SUM(ps.stl) / ROUND(hg.hg + ag.ag), 1) AS stl,
ROUND(SUM(ps.blk) / ROUND(hg.hg + ag.ag), 1) AS blk,
ROUND(SUM(ps.tov) / ROUND(hg.hg + ag.ag), 1) AS tov,
ROUND(SUM(ps.pf) / ROUND(hg.hg + ag.ag), 1) AS pf,
ROUND(SUM(ps.pts) / ROUND(hg.hg + ag.ag), 1) AS pts,
ROUND((hg.home_opponent_scored + ag.away_opponent_scored) / ROUND(hg.hg + ag.ag), 1) AS opponent_pts
FROM public.player_stats AS ps
LEFT JOIN public.teams AS t
ON ps.team_id = t.id
LEFT JOIN (
SELECT `enter code here`
home_team_id,
COUNT(
CASE
WHEN home_team_score > away_team_score THEN 1
END
) AS home_game_wons,
COUNT(
CASE
WHEN home_team_score < away_team_score THEN 1
END
) AS home_game_losses,
SUM(away_team_score) AS home_opponent_scored,
COUNT(home_team_id)::decimal AS hg
FROM public.games
WHERE season = '2019-20' AND playoff = false
GROUP BY home_team_id
) AS hg
ON ps.team_id = hg.home_team_id
LEFT JOIN (
SELECT
away_team_id,
COUNT(
CASE
WHEN home_team_score < away_team_score THEN 1
END
) AS away_game_wons,
COUNT(
CASE
WHEN home_team_score > away_team_score THEN 1
END
) AS away_game_losses,
SUM(home_team_score) AS away_opponent_scored,
COUNT(away_team_id)::int AS ag
FROM public.games
WHERE season = '2019-20' AND playoff = false
GROUP BY away_team_id
) as ag
ON ps.team_id = ag.away_team_id
WHERE ps.season = '2019-20' AND ps.playoff = false
GROUP BY
t.name,
t.short_name,
hg.home_game_wons,
hg.home_game_losses,
hg.home_opponent_scored,
ag.away_game_wons,
ag.away_game_losses,
ag.away_opponent_scored,
hg.hg,
ag.ag
ORDER BY games_won DESC, games_loss ASC;
EXPLAIN |
первые 29 строк
следующие 28 строк
введите описание изображения здесь
Sort (cost=45826.48..45873.10 rows=18648 width=852) (actual time=51.570..51.575 rows=30 loops=1)
Sort Key: ((hg.home_game_wons + ag.away_game_wons)) DESC, ((hg.home_game_losses + ag.away_game_losses))
Sort Method: quicksort Memory: 40kB
Buffers: shared hit=1031 read=247
-> Finalize GroupAggregate (cost=28708.80..37489.71 rows=18648 width=852) (actual time=39.190..51.507 rows=30 loops=1)
Group Key: t.name, t.short_name, hg.home_game_wons, hg.home_game_losses, hg.home_opponent_scored, ag.away_game_wons, ag.away_game_losses, ag.away_opponent_scored, hg.hg, ag.ag
Buffers: shared hit=1031 read=247
-> Gather Merge (cost=28708.80..30847.76 rows=10969 width=348) (actual time=38.346..50.761 rows=57 loops=1)
Workers Planned: 1
Workers Launched: 1
Buffers: shared hit=2014 read=342
-> Partial GroupAggregate (cost=27708.79..28613.74 rows=10969 width=348) (actual time=33.335..44.570 rows=28 loops=2)
Group Key: t.name, t.short_name, hg.home_game_wons, hg.home_game_losses, hg.home_opponent_scored, ag.away_game_wons, ag.away_game_losses, ag.away_opponent_scored, hg.hg, ag.ag
Buffers: shared hit=2014 read=342
-> Sort (cost=27708.79..27736.22 rows=10969 width=216) (actual time=32.724..33.952 rows=10609 loops=2)
Sort Key: t.name, t.short_name, hg.home_game_wons, hg.home_game_losses, hg.home_opponent_scored, ag.away_game_wons, ag.away_game_losses, ag.away_opponent_scored, hg.hg, ag.ag
Sort Method: quicksort Memory: 3275kB
Worker 0: Sort Method: quicksort Memory: 2665kB
Buffers: shared hit=2014 read=342
-> Hash Left Join (cost=2077.34..26972.71 rows=10969 width=216) (actual time=0.986..15.344 rows=10609 loops=2)
Hash Cond: (ps.team_id = t.id)
Buffers: shared hit=1988 read=342
-> Merge Left Join (cost=2060.14..26926.34 rows=10969 width=172) (actual time=0.926..12.449 rows=10609 loops=2)
Merge Cond: (ps.team_id = ag.away_team_id)
Buffers: shared hit=1981 read=342
-> Merge Left Join (cost=1030.29..25759.18 rows=10969 width=144) (actual time=0.554..9.803 rows=10609 loops=2)
Merge Cond: (ps.team_id = hg.home_team_id)
Buffers: shared hit=1941 read=342
-> Parallel Index Scan using IDX__PLAYER_STATS_1 on player_stats ps (cost=0.43..24592.03 rows=10969 width=88) (actual time=0.066..5.746 rows=10609 loops=2)
Index Cond: (((season)::text = '2019-20'::text) AND (playoff = false))
Buffers: shared hit=1906 read=336
-> Sort (cost=1029.86..1029.95 rows=37 width=60) (actual time=0.483..0.493 rows=30 loops=2)
Sort Key: hg.home_team_id
Sort Method: quicksort Memory: 27kB
Worker 0: Sort Method: quicksort Memory: 27kB
Buffers: shared hit=35 read=6
-> Subquery Scan on hg (cost=1028.06..1028.89 rows=37 width=60) (actual time=0.454..0.464 rows=30 loops=2)
Buffers: shared hit=35 read=6
-> HashAggregate (cost=1028.06..1028.52 rows=37 width=60) (actual time=0.452..0.460 rows=30 loops=2)
Group Key: games.home_team_id
Buffers: shared hit=35 read=6
-> Bitmap Heap Scan on games (cost=24.94..1013.50 rows=832 width=12) (actual time=0.113..0.282 rows=847 loops=2)
Recheck Cond: ((season)::text = '2019-20'::text)
Filter: (NOT playoff)
Heap Blocks: exact=14
Buffers: shared hit=35 read=6
-> Bitmap Index Scan on IDX__GAMES_2 (cost=0.00..24.73 rows=832 width=0) (actual time=0.098..0.099 rows=847 loops=2)
Index Cond: (((season)::text = '2019-20'::text) AND (playoff = false))
Buffers: shared hit=7 read=6
-> Sort (cost=1029.86..1029.95 rows=37 width=32) (actual time=0.369..0.373 rows=30 loops=2)
Sort Key: ag.away_team_id
Sort Method: quicksort Memory: 27kB
Worker 0: Sort Method: quicksort Memory: 27kB
Buffers: shared hit=40
-> Subquery Scan on ag (cost=1028.06..1028.89 rows=37 width=32) (actual time=0.350..0.355 rows=30 loops=2)
Buffers: shared hit=40
-> HashAggregate (cost=1028.06..1028.52 rows=37 width=32) (actual time=0.349..0.353 rows=30 loops=2)
Group Key: games_1.away_team_id
Buffers: shared hit=40
-> Bitmap Heap Scan on games games_1 (cost=24.94..1013.50 rows=832 width=12) (actual time=0.068..0.197 rows=847 loops=2)
Recheck Cond: ((season)::text = '2019-20'::text)
Filter: (NOT playoff)
Heap Blocks: exact=14
Buffers: shared hit=40
-> Bitmap Index Scan on IDX__GAMES_2 (cost=0.00..24.73 rows=832 width=0) (actual time=0.062..0.062 rows=847 loops=2)
Index Cond: (((season)::text = '2019-20'::text) AND (playoff = false))
Buffers: shared hit=12
-> Hash (cost=13.20..13.20 rows=320 width=52) (actual time=0.039..0.040 rows=37 loops=2)
Buckets: 1024 Batches: 1 Memory Usage: 11kB
Buffers: shared hit=4
-> Seq Scan on teams t (cost=0.00..13.20 rows=320 width=52) (actual time=0.024..0.031 rows=37 loops=2)
Buffers: shared hit=4
Planning Time: 1.586 ms
Execution Time: 51.999 ms