"""add composite index (user_id, created_at, id) on comparison_record C 端「我的比价记录」列表(GET /api/v1/compare/records)是 `WHERE user_id=? ORDER BY created_at DESC, id DESC LIMIT n` —— 原来只有单列 user_id 索引, 过滤完还要把该用户的**全部**记录取出来排序才能拿前 n 条,重度用户随记录数线性变慢。 本复合索引的反向扫恰好等于 (created_at DESC, id DESC),规划器直接取前 n 条、免排序。 列序 (user_id, created_at, id) 与查询一一对应,不要调整。 Revision ID: comparison_user_created_idx Revises: merge_active_phone Create Date: 2026-07-21 """ from __future__ import annotations from alembic import op revision = "comparison_user_created_idx" down_revision = "merge_active_phone" branch_labels = None depends_on = None INDEX_NAME = "ix_comparison_user_created" COLUMNS = ["user_id", "created_at", "id"] def upgrade() -> None: bind = op.get_bind() if bind.dialect.name == "postgresql": # 线上 comparison_record 已有数据量,普通 CREATE INDEX 持表写锁会阻塞比价 harvest 写入; # 用 CONCURRENTLY 不锁表(须脱离事务,autocommit_block 切到自动提交)。 # 同 comparison_status_created_idx 的做法。 with op.get_context().autocommit_block(): op.create_index( INDEX_NAME, "comparison_record", COLUMNS, unique=False, postgresql_concurrently=True, ) else: op.create_index(INDEX_NAME, "comparison_record", COLUMNS, unique=False) def downgrade() -> None: bind = op.get_bind() if bind.dialect.name == "postgresql": with op.get_context().autocommit_block(): op.drop_index( INDEX_NAME, table_name="comparison_record", postgresql_concurrently=True, ) else: op.drop_index(INDEX_NAME, table_name="comparison_record")