From c5abdc1186fd661098ebc34bc798e89b31d2b3d0 Mon Sep 17 00:00:00 2001 From: jtrzupek Date: Sun, 7 Jun 2026 21:12:22 +0200 Subject: [PATCH] migration(0021): raise scene_tags.tag_id statistics target to 1000 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Completes the literal-tag_id perf fix — the planner's MCV stats on tag_id are what let it pick the index-walk for common tags. Default target (100) covers only the top ~100 tags; 1000 extends correct cardinality estimates to mid-tier tags. Co-Authored-By: Claude Opus 4.8 --- .../20260607_0021_scene_tags_tag_id_stats.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 alembic/versions/20260607_0021_scene_tags_tag_id_stats.py diff --git a/alembic/versions/20260607_0021_scene_tags_tag_id_stats.py b/alembic/versions/20260607_0021_scene_tags_tag_id_stats.py new file mode 100644 index 0000000..4577a30 --- /dev/null +++ b/alembic/versions/20260607_0021_scene_tags_tag_id_stats.py @@ -0,0 +1,31 @@ +"""scene_tags.tag_id statistics target — MCV captures common tags + +Revision ID: 0021_scene_tags_tag_id_stats +Revises: 0020_scene_tags_tag_id_index +Create Date: 2026-06-07 + +Perf (2026-06-07): dopełnia 0020. Z literalnym tag_id (scenes.py resolvuje slug→id) +planner używa statystyk MCV kolumny scene_tags.tag_id by poznać kardynalność tagu i +wybrać index-walk po created_at zamiast materializować wszystkie scene_tags +(tag-filtered listy 4-12s → ~20ms). Domyślny statistics target (100) łapie tylko +~top-100 tagów; podnosimy do 1000 by mid-tier tagi też miały poprawne estymaty. + +ANALYZE NIE w migracji (ciężki/lockujący) — autovacuum przeliczy po zmianie targetu; +na prodzie wykonano ANALYZE ręcznie przy wdrożeniu. +""" +from collections.abc import Sequence + +from alembic import op + +revision: str = "0021_scene_tags_tag_id_stats" +down_revision: str | None = "0020_scene_tags_tag_id_index" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + op.execute("ALTER TABLE scene_tags ALTER COLUMN tag_id SET STATISTICS 1000") + + +def downgrade() -> None: + op.execute("ALTER TABLE scene_tags ALTER COLUMN tag_id SET STATISTICS -1")