AI 查询优化进入热路径,先给推理留固定预算
AI 查询优化进入热路径,先给推理留固定预算
把学习型基数估算或连接顺序搜索放进优化器,最先要回答的不是“模型能否找到更优计划”,而是它会不会挤占解析、优化和执行资源。模型调用一旦进入热路径,排队与缓存未命中都可能让优化阶段本身成为延迟来源。
本文讨论一个可验证的边界:AI 模块只能使用预留预算;预算不足时回退到已有 CBO。是否启用、阈值取值和预期收益都应由当前版本、SQL 集和压测结果决定。
高并发下先观察什么
模型推理的耗时要同优化队列长度、CPU 利用率和计划缓存命中率一起看。只看 CPU 容易误判:缓存未命中或锁竞争也会让请求排队,即使机器总体利用率并不高。
常见风险有三类:推理线程与执行线程争抢核数;训练集覆盖不到的谓词组合导致估算误差扩大;参数化 SQL 的缓存键设计不当,造成重复推理。它们不是模型特有的“故障”,但一旦落入同步路径,影响会被并发放大。
用预算决定是否调用模型
可以把 AI 优化器当作一类有容量上限的服务。需要提前定义:最大并发、最大排队等待时间、模型超时,以及回退模式。预算不必追求一个通用公式,先在代表性 SQL 集上测出基线,再用保守阈值上线;阈值应随硬件、模型版本和负载变化重新校准。
回退应当是正常分支,而不是错误处理。建议记录回退次数、原因、回退后的执行计划和查询耗时,以便确认模型带来的收益没有被优化开销抵消。
一个最小的准入控制器
下面的示例只表达控制逻辑:超过并发上限或近期延迟超过阈值时,选择 CBO。真实实现还需要处理取消、指标采样和缓存淘汰策略。
#include <atomic>
enum class OptimizerMode { Ai, Cbo };
class AiAdmission {
public:
AiAdmission(unsigned limit, double latency_limit)
: limit_(limit), latency_limit_(latency_limit) {}
OptimizerMode acquire(double recent_latency_ms) {
auto current = active_.load(std::memory_order_relaxed);
if (current >= limit_ || recent_latency_ms > latency_limit_) return OptimizerMode::Cbo;
active_.fetch_add(1, std::memory_order_acq_rel);
return OptimizerMode::Ai;
}
void release() { active_.fetch_sub(1, std::memory_order_release); }
private:
unsigned limit_;
double latency_limit_;
std::atomic<unsigned> active_{0};
};
这里的 acquire 与 fetch_add 之间仍可能出现竞争;工程代码应使用 CAS 循环或信号量,保证上限不会被并发请求穿透。缓存命中路径也应绕过该控制器,避免把不需要推理的请求纳入限流。
上线检查
灰度时用同一批脱敏 SQL 做影子比较,验证语义并记录计划变化、优化耗时和端到端分位延迟。模型、特征编码和阈值都应可回滚。队列开始积压或计划差异无法解释时,先关闭模型路径并保留样本,别让新模块拖着查询入口一起排队。
更多推荐

所有评论(0)