Skip to content

perf(history): 有界索引遍历历史窗口与压缩候选 - #1725

Draft
ChrAlpha wants to merge 2 commits into
felinics:refactor/context-prepfrom
ChrAlpha:perf/history-checkpoint-reads
Draft

ChrAlpha wants to merge 2 commits into
felinics:refactor/context-prepfrom
ChrAlpha:perf/history-checkpoint-reads

Conversation

@ChrAlpha

@ChrAlpha ChrAlpha commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Author

  • Human
  • Agent

Type

  • bug
  • feat
  • test

Summary

本 PR 叠在 #1724 上,base 为 refactor/context-prep。合入顺序为 #1724 → #1725;#1724 合入后,再同步 main 并将本 PR 的 base 改回 main。

#1724 已把 chat / Discuss 的历史窗口统一成 ListHistoryWindow,每步只取键、再按主键计量内容。但会话行数被低估时,递归仍可能每一步都扫描、排序会话内的键;压缩候选也仍先计量全部积压,再取本次预算窗口。本 PR 在它的统一接口上补齐有界索引遍历和压缩候选读取。

索引使用普通 CREATE INDEX,建索引期间会持有 SHARE 锁并阻塞该表写入;生产数据规模下的建索引耗时与发布窗口仍需验证。

Related Issues

Validation

当前 head 00dd730df6cc2d6e71fdbb1d54063760d9035645;父 PR head 594956162f2f98265d9c3bb173e8f91ecb061c5c,相对它为 14 个文件、+572/-208。通过普通 merge 衔接,保留原已发布提交。

本次实际执行:

  • go run github.com/sqlc-dev/sqlc/cmd/sqlc@v1.31.1 generate:通过。
  • go test -count=1 -p 4 -timeout 180s ./internal/agent/... ./internal/chat/... ./internal/channel/... ./internal/contextview/... ./internal/db/...:通过。
  • 独立本地 PostgreSQL 15.19,通过项目 embedded migration runner 从空库迁移至 173,dirty=false;0173 的 down/up/up 在事务内执行成功。
  • go test -tags=integration -count=1 ./internal/db -run '^TestHistoryCheckpointCandidate':通过,实际连接上述 PostgreSQL,覆盖保留行、截止点、truncated、字节预算及调用组边界。
  • go test -tags=integration -count=1 -p 1 -timeout 180s ./internal/chat/... ./internal/agent/application ./internal/agent/context/compaction ./internal/channel/discuss ./cmd/agent:通过。
  • 历史窗口对拍补充相邻会话数据与 truncated 断言,验证索引遍历不会读入其他会话,checkpoint 截止位置保持有效;2 万行执行计划守卫通过。
  • 受影响 compaction、message、db、application 包的 golangci-lint:通过;git diff --check 通过。
  • 对比父 PR,message 服务、turn-response 加载、Discuss 与 continuation 的生产代码没有额外改动。

待完成:在项目 PostgreSQL 18 / Cloud RLS 环境复验,生产规模索引发布评估,以及开发栈、真实 UI 和截图验收。以上自动化结果不代表 Human QA,PR 保持 draft。

Screenshots / Recordings

当前环境提供的旧验收目录未挂载,Docker CLI/socket 缺失,旧开发栈地址无法连接。已恢复 Go 工具链并用独立本地 PostgreSQL 完成上述验证;这不能替代真实应用验收。仍需恢复开发环境,在真实聊天页面验证长历史加载、压缩后继续与刷新,再通过 gh --attach 上传证据。

PR description prepared by an Agent.

Human QA

  • Human QA passed

history checkpoint 的几个有界读取在规划器低估会话行数时会退化,压缩候选
读取还会在截到预算之前计量整段积压:

- 历史加载与 turn response 的回溯每步按会话等值条件 LIMIT 1。会话被估成
  约 1 行时(统计还没见过的会话,或增长快于 ANALYZE 的会话),"扫描整个
  会话再排序"与有序索引代价持平,规划器改用 idx_bot_history_messages_session_reply
  再排序,每一步都扫完整个会话并解出每一行的 content 与 metadata:3.4k 行、
  10 MB 的会话一次 11 s,强制单行估计下 30k 行的会话一次 90 s 以上。
- 压缩候选读取对检查点之后的每一行计算 octet_length(content::text) 后才截到
  max_bytes,100 MB 积压每个 pass 约 350–420 ms;compactRows 逐个 pass 重读,
  追平积压是平方级的。低估时内联的 crossing_group 聚合按行重算,一次 7.6 s。

0172 加部分索引 idx_bot_history_messages_context_order,按轮次顺序收录上下文行
(可见、已入轮、非 passive_sync),谓词与这些读取写出的过滤条件一致。

- 回溯的每一步取上下文顺序索引中紧邻上一行的那一行,下界取自上一行自己的值
  而不是会话等值条件,规划器把它当作一个范围里的下一项,不会再规划成扫描
  并排序整个会话;遇到别的会话或检查点范围外的行即结束。起点与是否截断的
  判断各只执行一次,最坏也只扫一次会话,计量放在 LIMIT 之外,只解出取到的行。
- 压缩候选读取改为从旧到新的有界回溯:先取检查点按引用保留、位于其位置之前
  的行,再取位置之后的行;越过预算后只继续读跨界调用组自己的 tool 行,组结束
  或超过 max_row_bytes 即停,不计量任何取不到的行,追平积压时每行只计量一次。
  candidate_count 换成 truncated,CountHistoryCheckpointCandidates 换成只判断
  是否还有候选的 HasHistoryCheckpointCandidates。
- 取 payload 的连接只按 id,规划器不会改为哈希整个会话的行。

哪些行被取用、truncated 以及调用组完整性都不变:在种子会话(3.4k 行/10 MB、
30k 行/100 MB、30k 条短消息等)上对位置、截止点、预算、max_row_bytes 与
kept id 组合比对新旧 SQL,19920 个用例结果完全一致。
@github-actions github-actions Bot added bug Fixes a bug or unexpected behavior change:migrations Adds, modifies, or removes database migrations change:server Changes backend code, configuration, or API contracts size:S PR size uses the larger of added or deleted lines, excluding generated files labels Nov 2, 2026
@github-actions github-actions Bot added size:L PR size uses the larger of added or deleted lines, excluding generated files and removed size:S PR size uses the larger of added or deleted lines, excluding generated files labels Nov 2, 2026
@ChrAlpha ChrAlpha changed the title perf(history): 按索引有界读取 checkpoint 历史,避免反复扫描积压 perf(history): 有界索引遍历历史窗口与压缩候选 Nov 2, 2026
@ChrAlpha
ChrAlpha changed the base branch from main to refactor/context-prep November 2, 2026 01:34
@github-actions github-actions Bot added size:S PR size uses the larger of added or deleted lines, excluding generated files and removed size:L PR size uses the larger of added or deleted lines, excluding generated files labels Nov 2, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Fixes a bug or unexpected behavior change:migrations Adds, modifies, or removes database migrations change:server Changes backend code, configuration, or API contracts size:S PR size uses the larger of added or deleted lines, excluding generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant