Главная гоняла 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. Нижняя граница в нём тоже не для красоты: без неё тест прошёл бы и в случае, когда счётчик перестал что-либо ловить
## Что сделано
Главная гоняла `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
Главная гоняла тяжёлый 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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Что сделано
Главная гоняла
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