Files
FabledSteward/plugins/traefik/migrations/versions/traefik_004_covering_indexes.py
T
bvandeusenandClaude Opus 5.5 31e93e96cf
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 1m18s
CI / unit (push) Successful in 1m28s
CI / publish (push) Successful in 2m3s
fix(traefik): the rows page reads every router's history in one index-only query (#5355)
#5355 "Traefik page doesn't load": /plugins/traefik/rows took 12-28 s.
It ran a query per router ever seen, and each raw row in the range was a
heap fetch. traefik_004 rebuilds the router index to cover the charted
columns and indexes scraped_at for the request chart; router_history reads
the current routers' buckets in one query.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 08:20:09 -04:00

35 lines
1.6 KiB
Python

"""Traefik reads answered from the index alone
The rows page and the request chart read every raw row in the chosen range.
With only (router_name, scraped_at) indexed, each of those rows was a heap
fetch: a random disk read on a database whose indexes no longer fit in
memory, which took the rows page to 12-28 s. Carrying the charted columns
in the index makes these index-only scans; scraped_at gets an index of its
own for the request chart, which filters on time across every router.
Revision ID: traefik_004_covering_indexes
Revises: traefik_003_access_log
Create Date: 2026-10-08
"""
from typing import Sequence, Union
from alembic import op
revision: str = "traefik_004_covering_indexes"
down_revision: Union[str, None] = "traefik_003_access_log"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.drop_index("ix_traefik_metrics_router_scraped", "traefik_metrics")
op.create_index("ix_traefik_metrics_router_scraped", "traefik_metrics", ["router_name", "scraped_at"],
postgresql_include=["request_rate", "latency_p95_ms", "error_rate_5xx_pct"])
op.create_index("ix_traefik_metrics_scraped", "traefik_metrics", ["scraped_at"],
postgresql_include=["request_rate", "error_rate_5xx_pct"])
def downgrade() -> None:
op.drop_index("ix_traefik_metrics_scraped", "traefik_metrics")
op.drop_index("ix_traefik_metrics_router_scraped", "traefik_metrics")
op.create_index("ix_traefik_metrics_router_scraped", "traefik_metrics", ["router_name", "scraped_at"])