从 32 秒到 24 毫秒:一次标量子查询消除的内核优化实录

导语:

同一条 SQL,业务代码一字未动,执行时间从 32 秒降到 24 毫秒。这不是索引的功劳,也不是硬件的功劳,而是优化器在 SELECT 列表的角落里,安静地做完的一次改写。本文基于金仓数据库《标量子查询消除的实践与思考》,完整复盘这次优化的来龙去脉。

一、一个工程师都熟悉的场景

在很多客户业务中,SQL 常常是这样组织的:SELECT 列表里挂着多个标量子查询(每个只返回一个值),用来对主查询每行数据做进一步处理;而且这些子查询结构相似,只是输出列不同

业务语义没毛病,可读性甚至很好。但执行层面藏着两个具体隐患:

  • 对外层表(如 S11)的每一行记录都要执行一次子查询,记录越多越慢;
  • 多个结构相似的子查询会被分别执行,造成资源浪费。

一句话:根本问题不在子查询本身,而在于子查询被不断重复地执行。

二、为什么不能直接改成 JOIN

SELECT 里的标量子查询改写成连接,听起来很自然。但内核层面必须先保证语义安全性(Equivalence),两个反例非常具体:

  • 子查询返回值不是标量:原查询应当报错;一旦改成连接,不仅不报错还返回多行------语义不等价。
  • 子查询使用 count :无匹配时 count 返回 0sum/max/min/avg 返回 NULL。若直接改成外连接,无匹配时会补 NULL,与原始的 0 不一致。

结论:不是所有标量子查询都能消除,必须有严格的等价性判定。

传统优化器的执行策略很朴素------完整执行外层查询,对每一行执行一次子查询,多个子查询分别执行。问题恰恰就在这里:每次子查询访问的数据其实是相同的,却被反复执行。

三、三步法

金仓数据库在 V009R002C014 版本中引入了一套标量子查询消除机制,整体思路三步走,把正确性判定和性能改写严格解耦。

第一步|能不能优化:等价性判定

目标不是"尽可能多消除",而是只识别绝对安全的优化机会。分析子查询结构,对聚集、窗口、UNION 等复杂子查询做约束性判定。回答:"消除之后结果会不会变?"

第二步|如何优化:子查询转外连接

通过等价性校验后,把目标列中的相关标量子查询转换为内联视图 ,与外部相关表做左外连接,后续优化策略接管。

为什么是左外连接?因为外层每行必须保留------这正是前一步等价性约束的要求。

第三步|进一步优化:相似子查询合并

如果目标列中存在多个可合并的标量子查询,合并为一个内联视图再与外部连接,直接消掉"重复执行"。

四、一组让人安静下来的数据

复现脚本:

sql 复制代码
create table t1(id numeric(10,1));
create table t2(id numeric(10,1));
insert into t1 values(generate_series(1,10000));
insert into t2 values(generate_series(1,10000));

select (select sum(id) from t2 where t1.id=t2.id) from t1;

测试结果:

  • 子查询未消除 :对 t1 的每一条记录都要对 t2 进行一次全表扫描,需要对 t2 表扫描 1 万次,耗时 32 秒
  • 子查询消除后 :对表 t2 只需要执行一次扫描,总执行时间约 24 毫秒

性能提升数量级明显------这是原文最克制也最准确的描述。

差距大约是 1300 倍。但更值得关注的不是倍率,而是:用户的 SQL 没有改一个字符,业务代码没有动一行,性能就跨越了一个数量级。这是优化器型优化和索引型优化最大的不同------它不要求业务做任何配合。

五、结语

标量子查询消除单独看是一个非常细的优化点,它不在发布会 PPT 上,也不会成为架构话题。但把它和近些年内核演进的其他动作放在一起看------CBO 细化、子查询解关联、连接重排序、谓词下推------会发现它们共享同一种气质:

  • 把用户写得自然的 SQL,在内核层面悄悄改写成执行得高效的 SQL;
  • 把正确性判定和性能改写严格分层,保守优先、宁缺毋滥;
  • 优化的收益不依赖业务改造,老系统直接受益。

它不喧哗,不要求用户为它做任何事,只是在 SELECT 列表的某个角落里,把本来要跑 32 秒的查询,安静地变成 24 毫秒。

而这恰恰是好的基础软件应有的样子。

相关推荐
jcbut4 小时前
在Linux上安装Kingbase 9
linux·kingbase·人大金仓·电科金仓
betazhou8 天前
电科金仓数据库V9版本Linux版本安装体验
linux·数据库·python·kingbase·电科金仓
熊文豪11 天前
标量子查询消除:一次让查询性能提升千倍的优化器手术
数据库·电科金仓
熊文豪21 天前
表空间目录自动创建:国产数据库云原生存储管理的关键演进
数据库·电科金仓
熊文豪2 个月前
政务数据安全实战:让敏感信息在用时脱敏、退场时彻底消失
政务·电科金仓
betazhou3 个月前
麒麟V10 SP3环境安装金仓
麒麟·kingbase·电科金仓
正在走向自律3 个月前
国产替代不掉链子:KingbaseES如何做到MySQL零感迁移
mysql·金融行业·医疗行业·电科金仓·能源行业·交通行业·政务行业
正在走向自律3 个月前
电科金仓MySQL迁移实战:一个技术专家的深度踩坑与突围笔记
数据库·mysql·电科金仓·kfs·kdts
熊文豪3 个月前
文档数据库替换:金仓数据库MongoDB兼容性全解析
数据库·mongodb·kingbasees·金仓数据库·电科金仓