688005c081bf26ab22567b76cb6a30a0a2e2fcdd
Some checks failed
Deploy / deploy (push) Has been cancelled
流程图提交量涨上去之后,先扛不住的是教师统计面板:它一条不带 limit 的 select
把整个时间窗的行拉进内存再用 JS 算,词云那个 3000 条上限是在 JS 里截的,行早就
全回来了。列表那边则是 `select({ flowchart: 整行, problem: 整行 })`,把
mermaid_code、flowchart_data、三个 AI 文本列和整张题目表一起拉回来,响应一个
都用不到(快照实测流程图行均 4.9KB、题目行均 2.2KB,10 行一页白拉 ~70KB,
limit=250 时 1.7MB)。
- 列表改成白名单列 flowchartListColumns,对齐 submission 那边的
submissionListColumns(那边同样刻意不取 code / info)。
- 题号 / 用户名筛选先解析成 flowchart_submission 自己的列,count 因此一个 join
都不用挂,回得到最小索引上的 index-only scan;筛条件落在驱动表上,规划器也走
得上 flowchart_user_time_idx / flowchart_problem_time_idx。
- 统计面板拆成五条各自和行数脱钩的查询:数值聚合、等级分布、各项平均分
(jsonb_each + group by)、词云原料(order by ... limit 3000)、谁没做。
每项满分改从词云那批行里顺手取,省掉一次 21 万行的排序。
- matchedUsers() 从 submission.ts 挪进 helpers.ts,两条统计共用。
拿生产快照(2134 条)复制一份、另插三行脏数据(标量 jsonb、数组 jsonb、分数和
满分写成字符串),新旧两版各跑 24 个请求组合:23 个逐字节一致;剩下 1 个只是三行
create_time 完全相同的记录先后不同 —— 既有的不确定性(ORDER BY create_time 不是
全序),留给后面的 keyset 分页一并解决。
把表灌到 5.3 万 / 21.3 万行实测(HTTP 端到端,5 次取最好,旧 → 新):
列表 limit=10 35 → 4 ms | 56 → 8 ms
列表 limit=250 36 → 5 ms | 54 → 8 ms
列表 offset=5万 108 → 39 ms | 57 → 45 ms
列表 按班级 33 → 4 ms | 53 → 8 ms
统计 全部时段 288 → 187 ms | 1169 → 704 ms
统计 一个班 143 → 43 ms | 388 → 129 ms
统计 一道题 94 → 194 ms | 339 → 277 ms
「统计 一道题」在 5 万行量级是退步的:那个筛选命中全表 23% 的行,PG 侧的 jsonb
算子比「原样输出让 Bun 去 parse」更费 CPU,要到 21 万行才反超。它跟的是筛出来的
行数、不跟总量走,200ms 的教师面板可以接受,没有再调。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Description
No description provided
Languages
TypeScript
58.5%
Vue
39.6%
Shell
1.3%
Dockerfile
0.5%