From 682249a3fd9a85c9861970a3fd4bb53aa587a948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Thu, 10 Sep 2026 15:26:25 +0800 Subject: [PATCH] =?UTF-8?q?perf(management):=20message=E8=A1=A5=E6=97=A0?= =?UTF-8?q?=E6=B8=A0=E9=81=93=E5=89=8D=E7=BC=80=E7=B4=A2=E5=BC=95=E2=80=94?= =?UTF-8?q?=E2=80=94=E4=BF=AE=E9=A9=BE=E9=A9=B6=E8=88=B1channel=3Dall?= =?UTF-8?q?=E8=B6=85=E6=97=B634s=E2=86=921.3s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 该回未回决赛圈点查(owner+talker定位末条消息)在channel=None时无渠道 前缀条件,现有索引全以channel打头用不上,服务器100万行实测dashboard 34~37s撞前端15s超时(ECONNABORTED);补(owner,talker,timestamp)索引 后实测1.3~1.8s。服务器已先行手工建索引止血,本迁移幂等兜底对齐。 模型+迁移双声明防autogenerate反DROP --- yunke-server/app/db/models.py | 12 ++++++ ...0a1b2c3_message_owner_talker_time_index.py | 41 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 yunke-server/migrations/versions/d8e9f0a1b2c3_message_owner_talker_time_index.py diff --git a/yunke-server/app/db/models.py b/yunke-server/app/db/models.py index 0cd3d01..72f1608 100644 --- a/yunke-server/app/db/models.py +++ b/yunke-server/app/db/models.py @@ -537,6 +537,18 @@ class Message(Base): "ix_message_fetched_at", "fetched_at", ), + # 该回未回决赛圈点查(owner+talker 定位末条消息)在 channel=None + # (全平台计数——管理驾驶舱 action_counts 复用)时无渠道前缀条件, + # 上面全部以 channel 打头的索引用不上,逐候选退化扫表+filesort: + # 2026-09-10 服务器实测 dashboard 34~37s 撞前端 15s 超时 + # (ECONNABORTED);补无渠道前缀索引后 1.3~1.8s(100 万行在线建 + # 索引 49s)。「模型+迁移双声明」防 alembic autogenerate 反 DROP。 + Index( + "ix_message_owner_talker_time", + "owner_account_id", + "talker_id", + "timestamp", + ), ) diff --git a/yunke-server/migrations/versions/d8e9f0a1b2c3_message_owner_talker_time_index.py b/yunke-server/migrations/versions/d8e9f0a1b2c3_message_owner_talker_time_index.py new file mode 100644 index 0000000..9aabaee --- /dev/null +++ b/yunke-server/migrations/versions/d8e9f0a1b2c3_message_owner_talker_time_index.py @@ -0,0 +1,41 @@ +"""message 补无渠道前缀索引 (owner_account_id, talker_id, timestamp) + +Revision ID: d8e9f0a1b2c3 +Revises: c9d0e1f2a3b4 +Create Date: 2026-09-10 + +背景:该回未回决赛圈点查在 channel=None(管理驾驶舱 action_counts)时 +无渠道前缀条件,现有索引全部以 channel 打头用不上——服务器 100 万行 +实测 dashboard 34~37s 撞前端 15s 超时;索引落地后 1.3~1.8s。 +幂等:sa.inspect 先查,存在即跳过(服务器已先行手工建同名索引,本迁移 +兜底对齐 schema 版本)。「模型+迁移双声明」防 autogenerate 反 DROP。 +""" +from collections.abc import Sequence + +import sqlalchemy as sa +from alembic import op + +revision: str = "d8e9f0a1b2c3" +down_revision: str | Sequence[str] | None = "c9d0e1f2a3b4" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + +_IDX = "ix_message_owner_talker_time" + + +def _has_index(bind) -> bool: + insp = sa.inspect(bind) + if not insp.has_table("message"): + return False + return _IDX in {ix["name"] for ix in insp.get_indexes("message")} + + +def upgrade() -> None: + if not _has_index(op.get_bind()): + op.create_index(_IDX, "message", + ["owner_account_id", "talker_id", "timestamp"]) + + +def downgrade() -> None: + if _has_index(op.get_bind()): + op.drop_index(_IDX, table_name="message")