做数据库这行久了,会对一些"看着无害"的写法格外敏感。DISTINCT 就是典型——它太好用了,开发为了保证结果不重复,几乎是条件反射地往 SQL 后面一加。可恰恰是这种习惯,在数据量越滚越大的生产环境里,慢慢攒成了难以察觉的性能债。
电科金仓 KES(KingbaseES)针对这个问题,没有走"业务层改 SQL、加索引"的老路,而是直接从优化器底层动刀,让数据库自己识别冗余去重并完成改写。整个过程零业务侵入,结果还保证完全一致。下面把它的来龙去脉讲清楚。
一、传统数据库处理 DISTINCT 的三个老毛病
多数传统关系型数据库对 DISTINCT 的处理逻辑非常固化,统一是"全量查数 → 全局排序 → 遍历去重"这一套。数据量小的时候开销可以忽略,可一旦量级上来,机械执行的代价就全暴露了。
无过滤全表去重,比如 SELECT DISTINCT a, b FROM s1;,数据库会完整扫描整张表,再对 a、b 组合做全局排序去重。全表扫描和全局排序是最吃 CPU、内存和磁盘 IO 的环节。百万级数据实测,这条简单语句耗时就到 464ms——单条不起眼,但高频并发下慢查询一堆积,接口超时、业务卡顿就来了。
常量精准查询的无效去重,这是传统优化器最突出的短板。SELECT DISTINCT a, b FROM s1 WHERE a=1 AND b=1; 这条语句里 a、b 的值已经被 WHERE 完全锁死,结果必然唯一,根本不需要去重。可传统数据库识别不出这种逻辑,照样跑完整套去重流程,实测约 30ms。看着短,但这类查询基本都是高频接口,长期累积的无效运算持续占着资源,是典型的隐性隐患。
多表关联去重会把问题进一步放大。比如:
SELECT DISTINCT s1.a, s2.b
FROM s1 INNER JOIN s2
ON s1.a=s2.b AND s1.a=5;
s1.a 被固定为 5,靠等值关联能直接推出 s2.b 也是 5,结果只会有一条。但传统数据库还是先做全量关联,再分组去重,实测 12ms,整个分组去重环节纯属多余。
二、KES 的双层递进优化
KES 把这套优化做成了两层,全程内核自动完成,不用改业务 SQL,也不用额外配索引。
第一层:DISTINCT 语义等价转成 GROUP BY。 优化器先做严格的语义一致性校验,确保结果不变的前提下,把原生去重改写成分组查询:
-- 原始 SQL
SELECT DISTINCT a, b FROM s1;
-- KES 内核自动改写
SELECT a, b FROM s1 GROUP BY a, b;
好处有两点:一是可以借助主键、唯一索引做键值裁剪,不必对所有字段统一排序,省下大量排序计算;二是分组语法更适配 KES 的并行查询机制,能把单线程排序拆到多线程并行跑。同样的百万级测试环境,464ms 直接降到 249ms,性能接近翻倍。
第二层:逻辑推导判定唯一结果,直接替换 LIMIT 1。 这是 KES 区别于传统数据库的核心。它能自主构建逻辑表达式树,靠常量传递、谓词传递这些编译原理技术,挖出查询条件里的隐藏约束。只要确认结果唯一,就直接舍弃去重和分组,换成 LIMIT 1。
单表常量场景:
-- 原始
SELECT DISTINCT a, b FROM s1 WHERE a=1 AND b=1;
-- 改写后
SELECT a, b FROM s1 WHERE a=1 AND b=1 LIMIT 1;
检索到第一条匹配数据就返回,30ms 降到 0.03ms,差不多千倍提升。
多表关联场景同理,靠谓词传递把过滤条件和关联条件串起来,推出 s2.b 必为 5:
SELECT s1.a, s2.b
FROM s1 INNER JOIN s2
ON s1.a=s2.b AND s1.a=5
LIMIT 1;
12ms 降到 0.08ms,百倍以上提升。
三、核心差异:智能优化器 vs 代价型优化器
很多人会问,为什么传统数据库做不了这种轻量优化?根子在优化器的工作逻辑。
传统优化器是典型的代价计算模式,只会在现有固定方案里核算 IO、CPU 开销,挑一条相对最优的路径。它机械执行 SQL 语法,不深入解析语义,哪怕查询里有明显冗余也识别不出来。说白了就是只会"算账选方案"。
KES 的现代化优化器走的是"逻辑推理 + 代价优选"双模式。除了基础的代价核算,还能通过构建逻辑表达式树做常量传递、谓词推导,主动挖掘 SQL 隐藏的逻辑约束,从根源上简化冗余流程——它是真正"读懂了业务查询逻辑"。
四、同类对比
为了客观验证,用同样的常量去重 SQL SELECT DISTINCT a, b FROM distinct_1 WHERE a=1 AND b=1; 与国内主流的 DM 数据库做了对比。DM 的优化器识别不出常量固定带来的结果唯一性,执行计划里完整保留 DISTINCT 步骤,照样全表扫描去重,不支持向 LIMIT 1 的智能改写。KES 则能快速识别冗余、自主改写、跳过所有无效操作。在智能化逻辑优化和内核自主改写能力上,KES 确实领先一步。
五、给日常使用的几点建议
写 SQL 不用刻意删 DISTINCT,KES 会自动识别冗余并改写;多表等值关联、固定常量筛选的场景,放心加,不会有额外开销;排查慢 SQL 时看执行计划,如果没有去重、分组算子,就说明触发了自动优化;保持版本更新,新版本对嵌套子查询、复杂关联的优化覆盖更广。
结语
DISTINCT 慢查询,问题大多不在关键字本身,而在优化器做不了逻辑推导,只能死板走流程。KES 用"DISTINCT 转 GROUP BY 精简排序"和"逻辑推导改写 LIMIT 1 消除无效去重"两层优化,把"全表遍历去重"改成了"匹配到即终止"。常规去重接近翻倍,常量精准和多表关联更是百倍、千倍的跨越。
在信创替换提速、高并发业务越来越多的当下,这种内核自带的自动优化能力,既能实打实降低资源消耗、提升效率,也能省下大量人工调优的工作量,为企业级核心业务系统提供了扎实的技术支撑。
需要的话,我可以把这篇整理成 Word 文档,或者调整成更偏技术评测、更偏市场宣传的版本。