Главная страница четырежды пересчитывает тяжёлый CTE статистики (#32) #43

Merged
NotBigGhost merged 1 commits from issue-32-stats-single-pass into dev 2026-09-09 20:41:43 +03:00
Collaborator

Что сделано

Главная гоняла SCORED_CTE пять раз, а не четыре, как было записано в задаче: лидерборд, три запроса профиля (общий итог, разбивка по фракциям, форма последних партий) и ещё раз итог — для блока активной группы. Четыре последних выбирали одни и те же строки одного игрока и отличались только агрегацией, а стоимость CTE растёт с числом партий во всём приложении, а не в группе игрока.

Теперь строки игрока тянутся одним запросом, а итог, разбивка по фракциям и форма считаются из них в Python. Фильтр по группе — фильтрация того же набора строк, поэтому блок активной группы не стоит отдельного прохода.

Итого: на главной 2 прохода вместо 5, у профиля — 1 вместо 3. Публичный профиль и /users/me/stats тоже подешевели.

Формула сглаженного рейтинга получила Python-версию (scoring.smoothed_score) рядом с SQL-версией и на тех же константах: в SQL она по-прежнему нужна лидерборду, где агрегация идёт по всем игрокам сразу. Две реализации одной формулы — известный источник расхождений (в #8 ровно так разъехался кэш-бастер аватара между Python и SQL), поэтому расхождение закрыто тестом.

Коммиты

  • 8d54f68 Статистика: один проход по строкам игрока вместо четырёх

Проверки

  • pytest — 93 passed (было 91). Существующие тесты статистики и профиля прошли без единой правки — то есть цифры не изменились, что и было главным ограничением задачи
  • Новый тест «профиль против лидерборда»: games, wins, win_rate, avg_place и score сверяются между Python-расчётом профиля и SQL-расчётом лидерборда
  • Новый тест на число проходов: считает запросы с WITH tie AS через SQLAlchemy-событие before_cursor_execute; фактически сейчас ровно 2, порог — не больше 2. Нижняя граница в нём тоже не для красоты: без неё тест прошёл бы и в случае, когда счётчик перестал что-либо ловить
  • npm run build — зелёный (фронтенд не менялся)

Отклонения от плана

Нет.

Closes #32

🤖 Generated with Claude Code

https://claude.ai/code/session_01BoiJK9ux8peeyjLb8TYjFf

## Что сделано Главная гоняла `SCORED_CTE` **пять** раз, а не четыре, как было записано в задаче: лидерборд, три запроса профиля (общий итог, разбивка по фракциям, форма последних партий) и ещё раз итог — для блока активной группы. Четыре последних выбирали одни и те же строки одного игрока и отличались только агрегацией, а стоимость CTE растёт с числом партий во всём приложении, а не в группе игрока. Теперь строки игрока тянутся **одним** запросом, а итог, разбивка по фракциям и форма считаются из них в Python. Фильтр по группе — фильтрация того же набора строк, поэтому блок активной группы не стоит отдельного прохода. **Итого: на главной 2 прохода вместо 5, у профиля — 1 вместо 3.** Публичный профиль и `/users/me/stats` тоже подешевели. Формула сглаженного рейтинга получила Python-версию (`scoring.smoothed_score`) рядом с SQL-версией и на тех же константах: в SQL она по-прежнему нужна лидерборду, где агрегация идёт по всем игрокам сразу. Две реализации одной формулы — известный источник расхождений (в #8 ровно так разъехался кэш-бастер аватара между Python и SQL), поэтому расхождение закрыто тестом. ## Коммиты - `8d54f68` Статистика: один проход по строкам игрока вместо четырёх ## Проверки - `pytest` — 93 passed (было 91). **Существующие тесты статистики и профиля прошли без единой правки** — то есть цифры не изменились, что и было главным ограничением задачи - Новый тест «профиль против лидерборда»: `games`, `wins`, `win_rate`, `avg_place` и `score` сверяются между Python-расчётом профиля и SQL-расчётом лидерборда - Новый тест на число проходов: считает запросы с `WITH tie AS` через SQLAlchemy-событие `before_cursor_execute`; фактически сейчас ровно 2, порог — не больше 2. Нижняя граница в нём тоже не для красоты: без неё тест прошёл бы и в случае, когда счётчик перестал что-либо ловить - `npm run build` — зелёный (фронтенд не менялся) ## Отклонения от плана Нет. Closes #32 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01BoiJK9ux8peeyjLb8TYjFf
Agent added 1 commit 2026-09-09 20:38:49 +03:00
Главная гоняла тяжёлый SCORED_CTE пять раз: лидерборд, три запроса профиля (итог,
разбивка по фракциям, форма последних партий) и ещё раз итог для активной группы.
Четыре последних выбирали одни и те же строки одного игрока и отличались только
агрегацией, а стоимость CTE растёт с числом партий во всём приложении, а не в
группе игрока.

Теперь строки игрока тянутся одним запросом, а итог, разбивка и форма считаются из
них в Python. Фильтр по группе — фильтрация того же набора, поэтому блок активной
группы не стоит отдельного прохода. На главной осталось два прохода вместо пяти,
у профиля — один вместо трёх.

Формула сглаженного рейтинга получила Python-версию рядом с SQL-версией, на тех же
константах: в SQL она нужна лидерборду, где агрегация идёт по всем игрокам. Чтобы
две реализации не разъехались (как однажды вышло с кэш-бастером аватара), добавлен
тест, сверяющий цифры профиля с цифрами того же игрока в лидерборде.

Второй тест считает запросы с SCORED_CTE на главной: без него оптимизация тихо
отъедет назад при следующей правке витрин.

#32

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BoiJK9ux8peeyjLb8TYjFf
NotBigGhost merged commit 4133c3c505 into dev 2026-09-09 20:41:43 +03:00
NotBigGhost deleted branch issue-32-stats-single-pass 2026-09-09 20:41:43 +03:00
Sign in to join this conversation.