查询计划 强化学习 2026 清单:4B 模型在 JOB 113 查询上省下 44.7% 延迟
资料名称: 查询计划 强化学习 ——《Training a 4B model to produce 81% faster query plans than Postgres》,Rohan Bansal 2026 年 9 月 16 日发布的长文原文
帖内资料: 方法全文、qorl 代码仓库、JOB 与 CEB 两个基准的论文出处、pg_hint_plan 扩展仓库
时间覆盖: 长文 2026-09-16 发布;qorl 仓库 2026-08-26 建库、2026-09-17 最后提交;pg_hint_plan 仓库 2026-10-15 有更新
许可与引用: 长文页给出可复制的 BibTeX 引用写法;qorl 仓库未标注许可证;pg_hint_plan 仓库许可证标记为 NOASSERTION
适用任务: 想把「模型产出计划—真实执行测量—按相对优势回传奖励」这套闭环搬到自己 PostgreSQL 库上的人,用来定变量、控噪声、选指标
这是一篇 2026 年 9 月的长文,作者用强化学习把一个 4B 的开源小模型训成了 Postgres 的查询计划改写器。页面公开,正文、公式、配图说明、参考文献和完整的引用写法都摆在页面上,代码仓库一并放出。
44.7% 是怎么算出来的
44.7% 说的是总延迟下降幅度,源头是 1.81x 这个加速比:1 除以 1.81 约等于 0.553,比原来少了 44.7%。这个 1.81x 是最终检查点在每条 JOB 查询上跑三次轨迹、最多拿到 15 个候选、再挑其中反馈最好的那个之后测出来的,几何均值加速比和总工作量加速比恰好同为 1.81x,113 条查询里 68 条变快、0 条变慢。
起点则是这个 4B 模型在 113 条查询中有 99 条拿不出可用计划。
这个闭环由哪几段接起来
作者自己写的智能体外壳叫 qo-agent,只给了模型六个工具:inspect_relation 看表结构、get_column_stats 拿列的规划器统计、get_plan 取默认计划或已提交候选的估计、evaluate_candidate 校验并执行候选、keep_default 直接收下默认计划、finish 收尾。
模型输出的是 PlanAction JSON,外壳把它编译成 pg_hint_plan 的提示注释,再拼到原 SQL 前面。pg_hint_plan 是第三方扩展,提示写成带加号的 SQL 注释,Postgres 自己忽略、扩展负责读。
在自己的库上怎么控制测量噪声
四段做法可以直接搬。
一是并发隔离:起 4 个 Docker 容器,每个固定 4 核、内存上限 8 GB,容器内用同样参数初始化 Postgres 并载入 IMDb;四个容器共用一个装了 113 条查询的队列,谁测完谁取下一条。容器少于 4 个训练会太慢,多于 4 个则 CPU 争用带来的噪声更多。
二是缓存预热:每条查询先反复跑,每跑一次用 EXPLAIN (ANALYZE, TIMING OFF, BUFFERS, FORMAT JSON) 把 shared hit blocks 和 shared read blocks 两个计数器取出来跟上一次比,两个计数相差都在 2% 以内、且计划没变,就算预热到位,随后连测 20 次。
预热至少两次才有的可比,最多五次就截断。
三是把 shared_buffers 调大:128 MB 对着 8.5 GB 的库,Postgres 每次执行都在 miss 自己的缓存;换到 2 GB 之后,无操作误判率从 5.0%/5.4% 降到 1.8%/1.2%,p90 查询从 13%/20% 降到 1.3%/0%,113 条查询的总耗时也从 95 秒降到 60 秒。
work_mem 从 4 MB 调到 32 MB 对噪声没有影响。典型的那条 job-13b,变异系数从 10.3% 掉到 0.9%,20 次全部落在 7 ms 之内。
四是判定方式:不单跑一次,而是顺序跑三组交错的(候选,默认)对,各取三次的中位数相比,相差不到 5% 算平手。
两个指标各自在说什么
几何均值加速比 S_geo 是每条查询「默认耗时 ÷ 候选耗时」连乘后开 N 次方,每条查询权重相同:一条快 2 倍、另一条慢到 0.5 倍,二者相抵正好 1.00x。总工作量加速比 S_workload 把整批查询当一件事,用默认耗时之和除以候选耗时之和,同一个例子算出来是 1.4x。作者的看法是前者衡量模型是不是真的学到了东西,后者衡量实用价值,两个一起看。
奖励被噪声骗过去时怎么兜
作者没有拿变异系数当目标,而是直接算误判率:把 20 次测量按 6 个一组滑窗 15 次,每个窗口内谁当候选、谁当默认各有 2 种可能,一共 120 种模拟;其中让一个与默认完全相同的候选被判成加速或减速的比例,就是这条查询的误判率。
训练时换掉了原版的 GRPO,改用锚定版本:先算每条轨迹的质量 q,再把基线 b 取成同组其余轨迹质量均值与 0 之间的较大者——这样一条轨迹不会因为只是最不坏就拿到正优势。优势 A = q b,再扣掉重复默认计划的 0.02 与整条轨迹没有有效候选的 0.1。速度比先截到 [0.1, 10] 再取对数,并用 0.05 的软阈值吸收测量噪声。
原始资料与地址
一共四处。长文原文是主来源,页面上按章节把方法与数据摊开,末尾给了可复制的 BibTeX。qorl 代码仓库是作者放出的实验框架,Python 3.
12、面向 Linux x86-64,用 uv sync --frozen 装依赖,实验分 calibrate、eval、sft、rl 四类,随机种子默认 42。JOB 出自 Leis 等人 2015 年的 PVLDB 论文,CEB 出自 Flow-Loss 论文,两篇按各自出版方许可获取。
pg_hint_plan 是驱动 Postgres 换计划所依赖的扩展,仓库与提示列表文档都公开。
────────────────
网址、许可证情况和两个基准的获取方式都列在下面,回复一下就能看到。